In the previous article on test automation, we mentioned that the tools we use in our projects (Selenium + Cucumber) work great when it comes to applications created on the Pega platform.
In this article, we would like to expand on this topic, by briefly presenting the process of creating such a framework for Pega.
Requirements
In order to work on test automation, we need a device with access to the Internet and – obviously – access to the Pega system which we will be testing. On said device, we will install the necessary tools. These tools include:
- Web browsers through which we will run our Pega application, with the help of automated tests;
- IntelliJ IDEA Community Edition – a development environment (IDE) used to create our automated tests;
- Apache Maven – a software project management tool. This is the core of our project. It manages the libraries and plugins used in the test automation code;
- Jenkins – an open-source CI/CD software which we use to run automated tests. These tests can be run manually, with the use of Jenkins, as well as automatically – through the Pega Deployment Manager – in such cases, we include a so-called Jenkins task that references our installation and runs automated tests for us.
Test scenarios
We will now present the process of preparing automated tests, based on the example of an application created in Pega 8.7.0. It is a simple application used to manage a fictional golf course. The case we will be testing is used to register a new membership in the system. Its life cycle is presented below.
The steps comprising this case are as follows:
- Choose member – a screen containing an autocomplete field where we select the person for whom we are registering a membership. For this test scenario, we’ll choose one of the existing golf club members.
- Choose membership – in this step, the user selects one of the membership plans, by clicking on one of the “Choose” buttons.
- The last step is a summary. Here, the user only needs to click “Submit”.
Our objective is to create a new case and successfully go through the steps described above – so that, in the end, the case status is “Resolved-Completed. For this purpose, as part of our project, we create a new file with the *.feature extension, in which we write a test scenario in the Gherkin language. This scenario might look like this:
Scenario: New Membership Happy path
Given User has access to "Golf Club" application
When User creates new case of type "New Membership"
Then User will be presented with "Choose member" screen
When user selects "Łukasz Sokolnicki" in Choose Member autocomplete field
And User clicks Submit button
Then User will be presented with "Choose membership" screen
When User selects "Ultimate" membership plan
And User clicks Submit button
Then User will be presented with "Summary" screen
When User clicks Submit button
Then case will be finished with "Resolved-Completed" status
First, we check the preconditions, with the use of the “Given” clause, i.e., we verify whether the user has access to the Pega system and whether they can log into the application called “Golf Club”. The sentence starting with “Given” is always at the beginning of the test scenario and we use it to check if all the pre-conditions for our test have been met.
Then, using sentences with the words “When … Then …”, we execute the individual steps of the process and – at the same time – we test the correctness of such execution. The part of the sentence starting with “When” describes the action that will be taken, while the part starting with “Then” describes the expected result of this action, i.e., the so-called. assertion.
In the above example, one can see that the “Then” part is used multiple times, e.g., “Then User will be presented with “(…)” screen”. This is purposeful and desirable, because it promotes reusability of the code and minimizes the developer’s workload, which we will try to explain below.
Test automation code
With at least one test scenario ready, the developer can begin their work. With the help of Selenium, they will program automated tests, based the test scenarios. Selenium is a framework that is available in many programming languages. At Clocklike Minds, we use the Java version.
In a nutshell, the developer’s job is to, on the one hand, “translate” test scenarios written in the Gherkin language – which is very “business-oriented” – into a programming language that can be compiled into an executable code. On the other hand, this code must perform actions in our web application on our behalf, using a web browser (so as to best reflect the real user actions).
Gherkin’s links to Java
Based on the test scenario, the developer creates code for automated tests. In our example, we will use the Java language (as we do in real projects). Generally, the code is “wrapped” in methods that do not return any data, and these methods are linked to the test scenario through an appropriate annotation. Each line of the test script, which starts with the Given, When, And, or Then keyword, has a corresponding method in the Java code. For example, there is a step in our scenario, where a golf club member needs to be selected from an “Autocomplete” drop-down list:
When user selects "Łukasz Sokolnicki" in Choose Member autocomplete field
The corresponding method in Java code will look like this:
@When("user selects \"Łukasz Sokolnicki\" in Choose Member
autocomplete field")
public void user_selects_member_in_choose_member_autocomplete_field() {
// body of the method goes here.
}
The annotation starts with the “@” symbol and the keyword corresponding to the first word in the test scenario. Then, a part of the text of the test scenario is placed in brackets. This identifies the method to be applied to that particular element of the test scenario, whenever the scenario is used. In other words, every time the sentence
“When user selects “Łukasz Sokolnicki” in Choose Member autocomplete field” appears in the test scenario, then the user_selects_member_in_choose_member_autocomplete_field() method will be applied.
Therefore, it is worth it to build multiple test scenarios using existing parts – as often as possible. In that way, we can minimize the programming resources needed to create automated tests and promote the reusability of previously created code. However, this is not the only way to do this. We can also transfer parameters directly from a test scenario (Gherkin) to a Java method. Such parameter in the above example could be the first and last name of a golf club member:
name of a golf club member:
@When("user selects {string} in Choose Member autocomplete field")
public void
user_selects_member_in_choose_member_autocomplete_field(String
string) {
// body of the method goes here.
}
As a result, we gain a lot from the reusability of the above method because we can create more scenarios for different club member data. These parameters can have different types, e.g.: {int}, {float}, {byte}. We can also create our own types where the developer includes a list of permissible values for a parameter – his solution facilitates the work of the Business Analyst who creates test scenarios.
In addition, the Gherkin language allows for the use of:
- optional words – such words are placed in brackets. Regardless of whether such words are present or not – the method will be identified;
- alternative words – words separated by a slash. It is enough for one such word to appear in the test scenario and the method will be identified.
Thanks to the above solutions, the developer can create an automatic test code which will later be widely reused in many test scenarios by the Business Analyst.
Web browser automation
Selenium is a framework used to perform operations in our web application through programming. In short, the way it operates comes down to two activities:
- Locating an element (e.g., a text box or a button) on the page,
- Performing an action on that element (e.g., clicking or entering a value).
In order to locate an element on the page, one can use both html attributes related to said element and css attributes. Of course, the best attribute is ID, but not every element on the page has it. If the given element does not, one can use the so-called xpath which is an expression build from more than one attribute. Xpath also gives the option of checking the value of a given html element, as well as traversing, i.e., referring to a parent or child element.
In the context of Pega, xpath is especially useful – but more on that in a moment.
Below, we’ve presented a method for logging into our application. There are 3 elements on the standard Pega login page, which we are interested in. There is a text field for user input, a text field for a password and a “Log in” button. Luckily for us, all of these items have an ID.
The Java code for this method looks as follows:
@Given("User has access to {string} application")
public void user_has_access_to_application(String appName) {
getDriver().get(getAppURL(appName));
getDriver().findElement(By.id("txtUserID")).sendKeys("user@golf");
getDriver().findElement(By.id("txtPassword")).sendKeys("rules123");
getDriver().findElement(By.id("sub")).click();
}
The Driver class has the findElement method which allows for finding an element in the Html code, based on a selected criterion. In our case, it is the ID, so the code looks like this: getDriver().findElement(By.id(…)). Since the findElement method returns an object of the WebElement class, we can
immediately perform the desired operation on it, e.g.,: …sendKeys(”…”), i.e., enter text, used for user and password text fields, or .click() for a button.
If a given element on the page does not have an ID, we must identify it with the use of another criterion, most often xpath. Such identification is greatly facilitated by Pega which provides the TestID field. It is an identifier generated automatically by the system for each UI element. If necessary, this identifier can be manually modified. The relevant field is presented below.
The value of this field is later reflected in the html code as an attribute named data-test-id. Note, however, that – by default – this attribute is invisible. This is due to performance considerations. For this attribute to be available, we need to add a role named PegaRULES:TestID to our test user’s access group.
TestID is used in the automated test code in the following manner:
@When("user selects {string} in Choose Member autocomplete field")
public void
user_selectes_member_in_choose_member_autocomplete_field(String
string) {
getDriver().findElement(By.xpath("//input[@data-test-
id='202207190751480441637']")).sendKeys("Łukasz Sokolnicki");
}
The use of TestID provided by Pega significantly facilitates the creation of automatic tests, because it allows for an easy identification of various elements on the website. We use it anytime we have the opportunity to do so. It also ensures that once the TestID identifier is assigned to an element, it will never change – e.g., as a result of an upgrade of the Pega version.
Further programming of automated tests is done following the same steps presented above, i.e.:
- We create a method;
- We assign an annotation to this method, which will connect the method to the corresponding part of the test scenario;
- We create the body of the method using Selenium, which gives us access to the content of the website from the level of the Java code.
If we run a code created in this way, we are able to see how all operations are automatically being performed by our program. As a result of these operations, a case should be created, in which all steps are processed and which eventually reaches the Resolved-Completed status.
Summary
The use of external tools Cucumber and Selenium gives us the opportunity to build a powerful framework for automated tests, which will test every “slice” of the Pega application for us, utilizing the user’s perspective. Thanks to said tools, we can test not only cases created manually, but also those that are initialized externally, e.g., with the use of a REST service or a file listener. We are also able to fully review the user portal and each of its features.