Test Driven Development for Pega Applications
Let’s face it: chances are, as a development team, you are not testing your Pega applications as thoroughly as you should be, and it’s time you started.
Fortunately, there are ways that you can begin to integrate this practice into your daily work – and ultimately into your organization as a whole. In this article, let’s discuss Pega’s testing functionality, how you can begin unit testing in Pega, and finally how you can leverage the power of test driven development using the Pega platform.
I learned programming in Java, and unit testing was a fundamental part of that development process to ensure code correctness. As unit testing evolved and became more formalized at the organizations for which I worked, automated testing suites, code coverage metrics, and continuous integration made the developers’ unit testing an integral part of their day-to-day work.
This focus led many individuals and organizations to adopt the concept of test-driven development (TDD). While a number of people disliked the idea, often because it was misrepresented to them in an extreme version, I was quickly won over by the approach. The philosophy of TDD is that you write all of your unit tests against a stub for the functionality that you intend to implement, based on the requirements for that functionality. Of course, having implemented nothing, all of these tests fail! (I would typically stub out my method calls in Java by having them throw an obvious exception.) However, as you build out the implementation, more and more of these tests begin to pass, so that you know you have implemented correctly when all of the tests are “green”.
Setting Up Unit Testing in Pega
Admittedly, you will face some resistance when you begin to advocate and eventually insist upon unit testing. For some people, it will always appear as a barrier to the ability to develop as rapidly as they would like. However, you must counter that argument by noting that there will be notably fewer defects (and we all hate those) and significantly shorter formal testing cycles as a result. Best of all, and especially for larger implementations where the likelihood of gaps becomes very large, you get real confidence that the application you are releasing is functionally correct.
So how does one go about it? Pega has some very good materials on the Pega Developer Network (PDN) on unit testing that a quick search will readily turn up, but it comes down to a few basic points:
- Create a new Application rule from your existing (or generated) Application. Let’s call it “MyAppDev”, copied directly from the MyApp Application rule.
- Create a new Access Group for developers that leverages that new Application. We can call this “MyAppDev:Administrator”, copied from MyApp:Administrator (or whatever Access Group the developers use). Developers, and developers only, should all get this Access Group, pointed at the MyAppDev Application Rule.
- Create a new, open RuleSet for testing MyAppDev, with its only dependency being the application layer it is intended to test. In this case, we are testing the MyApp implementation layer, so call it MyAppTest. As of Pega 7.1.8, there is also a checkbox on the Category page that indicates whether this RuleSet is intended to store test cases. Add this RuleSet to the new Application rule.
Note that it will behoove you to keep the testing RuleSet Version in sync with the implementation RuleSet Version, since changes in the user stories may affect the outcome of the tests in different, valid ways. For example, a user story’s acceptance criteria may be invalidated by a later user story as the business adjusts its expectations based on customer feedback. By keeping the versions in sync, each version will execute correctly based on the acceptance criteria in effect at the time the code and corresponding test was written.
You now have something similar to a Production RuleSet, except it’s much the opposite in that it will never go to production. Furthermore, only developers will ever have access to this RuleSet, and it will never be packaged or otherwise moved into higher environments. Lastly, if you have framework and implementation layers, it likely warrants multiple test RuleSets in order to ensure that each layer is behaving in the way that is expected – each of which might be different than the other based on implementation requirements that override framework behaviors. It is not unreasonable even to have a test rule set for each of your application RuleSets. This helps consolidate like functionality and avoids the creation of unnecessary dependencies. If you make use of Pega’s branching capabilities, you will also want to create branched versions of each of your testing RuleSets as you find a need to branch their corresponding application RuleSet.
Basic Unit Tests and Code Coverage
The Test RuleSet is essentially the harness against which you will build test activities, each of which should be associated with a user story (if using Scrum) and its individual acceptance criteria. Since those criteria are by definition intended to be testable, or you would not have allowed the user story to enter the Sprint (right?), specific code-level tests can be performed to ensure correctness. To put it simply, if there are four acceptance criteria, then there should probably be four unit tests, or some good reasons why it can’t be tested in this manner.
When you have completed the story and believe that you have implemented it correctly, it’s time to prove it. Create named activities for each acceptance criteria, such as US123-AC1, or even something more descriptive so long as it identifies the use case and acceptance criteria distinctly.
After that, each test becomes a matter of three basic steps:
- Set up the initial data structure anticipated by the functionality, if any.
- Execute the functionality to be tested.
- Test the resulting data structures for correctness. (This may include checking saved objects by retrieving them via an Obj-Open or Data Page. You could even invoke a test-specific Validation rule!) If the data is correct, then great: your job is done here. If not, fail the Activity.
It is vitally important that you don’t skimp on testing for correctness across as wide a set of scenarios as possible, especially if it can be done iteratively! If you are the Lead System Architect on the project, you should check the rules being added to this Rule Set frequently to make sure everyone is incorporating testing into their development habits, especially early on. It can also be handy to start building out a test harness that includes helper activities and data transforms for building common objects so that developers do not have to re-invent the wheel for each test: make your test code reusable, too!
Building Testable Rules
You will find, as you begin to create your tests, that it becomes a much easier task if the functionality is created in such a way that it is – well, testable. What this typically means is a heavier use of parameters and less dependency on an implicit underlying application state, all of which leads to more reusable rules and a more manageable application overall. This is of course a best practice and goal for any Pega development, so you will help yourself twice!
Test Cases and Test Suites
Pega has some testing features built in, including the ability to run test cases and execute test suites – collections of tests. (You can find these rule types listed in the SysAdmin category of the Records tab.) To leverage this functionality, you need to grant yourself the role of PegaRULES:AutoTest, which means you will want to add it to the testing Access Group discussed in the prior section.
When you have a test activity that is passing, run it from the Developer Portal by selecting the Test Cases tab on the Activity rule form. Selecting the “Record new test case” button will launch an execution of the activity, just as if you had selected “Run” from the Action menu. This will save the Test Case as a successful execution for later reference, as the Test Case will expect the same results or flag the test as a failure.
Test Cases can be added to a Test Suite, which begins to build out a more structured testing module across the application. These Test Suites should be focused on logical components of the application so that they contain groups of tests that are all related. For instance, you might have a Test Suite called “Payments” that focuses on payment integration, another called “Orders” that tests the ordering component, and so on.
These Test Suites can be run in the background on scheduled intervals – say every hour from 8AM to 6PM – by an Agent (RunTestSuitesFromAgent) for continuous testing to prevent regression. Check the results and determine what failures have arisen, or – better yet – have Pega email the team (CompletedTestSuite Correspondence Rule) via a specific email account if something breaks! The designer studio allows you to look at the tests for your system, view reports, and schedule when the tests will run.
Test Driven Development
Congratulations! You now have people unit testing regularly. They have good code coverage, create Test Cases, and you have Test Suites running consistently. What next? Well, turn everything on its head, of course!
Test Driven Development (TDD) is a different way of developing components, and it does so by stubbing out the function to be built and building the unit tests first. Using the same principles, create tests for your acceptance criteria, but don’t add them to a test case or suite quite yet. Yes, of course they will fail because they are checking functionality that does not exist, but here is where the magic begins. As you start implementing the feature(s) requested, more and more of these tests will pass, at which point you know that the acceptance criteria are being met. When all your tests pass, then you’re done! Now add them to your Test Cases and Test Suites to ensure that no future regression occurs.
This testing strategy is proactive rather than reactive, and by putting the horse before the cart, you drive toward the goal of completion rather than completing a task and then having to psychologically “go back” and unit test. It’s a powerful methodology, and I highly recommend trying it.
Many of you will have already caught on to the fact that not everything will be testable in this manner. User interface requirements, as well as a number of other rule types, are missed, but a great deal can be caught and that is what is important. Data Pages, Activities, Reports, Validations, and many, many more rule types can be effectively tested and their functionality proven in a consistent manner.
I hope that you start integrating some of these practices into your organization. (If you need some help, I know a guy.) I believe it is best to start small and gain momentum, so don’t necessarily jump in and insist that everyone start using TDD right away! A cultural shift will need to evolve and be supported not only by business and technical leadership, but as a grass roots effort and hallmark of good programming practice.
The best developers I have known were the ones that tested their code the most.
Colin Campbell is CEO and Principal Consultant at Stratosphere Technical Consulting, LLC. He has a background in software development and architecture, service oriented architectures, API design and development, and business process management. He is a Pega Certified Lead System Architect (CLSA).
The following Pega Developer Network articles were referenced in the writing of this article. Registration is free.