Test Automation Patterns and Good Practices
How to make sure your test automation not only makes your team move faster, but in the right direction.
Test automation, or automating the execution of your tests, provides several advantages: it saves your team time, resources, and the headache of having to do everything manually. However, test automation alone doesn’t guarantee success. If you don’t set up tests in the right way, you end up with the same bad results (just delivered a whole lot faster!).
Here are some patterns and best practices for test automation, so you can be sure your team is getting maximum value from your automation efforts.
Test Code Review
Tests (at the unit, API, UI, and performance level) should be reviewed to analyze their quality and to find mismatches or bad practices. For example, a set of tests could be fulfilling their coverage criteria, sufficiently invoking the intended code sections, but if proper assertions aren’t written, the tests will be useless in identifying problems (that is, they will only execute the code, and not analyze whether what it does is good or not).
The practice of test code review also allows another person with a fresh perspective to add more tests that evaluate other aspects of the system, as well as verify that system requirements are clear and met.
As mentioned, assertions make the difference between a test that only tries out the code and one that really identifies problems. Each test automation tool verifies responses by providing a way to determine if a test has failed.
On the other hand, it’s also best to pay special attention in the definition of assertions to avoid false negatives and false positives, since an overly generic assertion can result in incorrectly valid or invalid tests.
Behavior-Driven Development (BDD)
BDD refers to Behavior-Driven Development. As the name implies, this isn’t a testing technique, but rather a development strategy (like TDD, test-driven development). A common language should be established for the business and engineers to be used as a starting point for development and testing. Typically, user stories are defined and later used as an input for test cases creation. Beyond the possibility of automation, the focus should be on using certain business requirements that can later be translated into acceptance tests.
One obvious advantage of BDD is that developers have clear specifications, so they can focus on what needs to be done—and in what way—at the business level. Like TDD where you have a method along with its tests, with BDD you already have an “acceptance test” at a business level.
Another advantage of the BDD approach is that it brings testability to the system. Thinking about functionalities in an independent way (as complete and involving all the layers of the system) guides a type of development that facilitates testing.
Page Object Pattern for UI Testing
When working with automation at any level, it’s essential to focus on a solution’s scalability and maintainability. That is, it shouldn’t take more time to resolve conflicts or update an automation framework than the time saved by the automatic execution. To achieve this, the correct use of design patterns is fundamental.
When writing automated tests, one begins to generate code that contains a lot of knowledge about the structure of the application, like the IDs of fields, buttons, and links, etc. Over time, the application will scale and be modified, so it’s important that tests can be maintained with minimal effort.
The Page Objects pattern allows you to reuse this knowledge of the application while making each change in the pattern have minimal impact on tests. It consists of completely decoupling what concerns the structure of the user interface from the test code, and encapsulating this information in objects that represent application interface elements. In this way, the Page Object pattern strengthens tests.
By following a BDD approach, these types of patterns should also be applied, since they are complementary practices. This also applies to any automatic verification at the graphic interface level, regardless of whether Selenium (for web), Appium (for mobile) or any other tool is used.
While data-driven testing goes beyond a design pattern and involves a whole testing approach, we include it in this post as part of good programming practices.
Essentially, automated tests are parameterized so that the same steps can be executed with diverse amounts of test data. That way, simply adding data to the data file creates new test cases.
The greatest benefit of doing this comes when the same sequence of steps is executed with different data sets, parameterizing both the input data and the expected output data.
Parallel Execution of Tests
Unit tests and API-level tests generally run faster than UI tests. On the other hand, automated tests at the graphic interface level require access to the end-to-end system and handling of interface elements so, they require more execution time. This is why different strategies like parallel execution have become really useful.
If you work on a web application and automate with Selenium (the most commonly used option) it’s a good practice to use Selenium Grid. With its multiple nodes, Selenium Grid has the advantage of easily combining operating systems with several browsers accessing the application. This leads to running several tests in parallel using the Grid reducing testing time.
When combining Selenium Grid with any integration tool as Jenkins, tests are triggered by connecting to the Grid and run on each node. Results are stored in association with the task (Job in Jenkins terminology) keeping track of the executions.
These are just some of the patterns and best practices you can use to improve your test automation.
With the right combination of tools and practices, you can move forward knowing test automation is propelling your team in the right direction.
What are some test automation practices you’ve found helpful? Any advice?
Leave a comment below!
Thank you to Feedspot for recently naming Abstracta as one of the top blogs for test automation!