BUT, automated UI tests are presumed to be hard to maintain and difficult to understand. Small changes in the webapp’s GUI have massive impact on the test suite to result in refactoring the test cases. Especially when the tests are built by screen recorder.
Another weakness is the response of UI tests. UI tests are perfect to avoid regression running on a CI server all night long. But what if the front-end developer wants to get quick feedback during development?
In this post we give a short introduction to UI testing at Camunda. We show how to design robust tests that are easy to maintain and how to get a quick response from your test suite during webapp development.
The UI Test Framework
The Camunda bpm stack currently includes four webapps built with HTML 5 and Angular JS: cycle, cockpit, Tasklist and admin. For that, we introduced Protractor, an E2E test utility for Angular applications.
An important argument for this framework is the seamless integration into our existing technology stack. Protractor is a Node.js based utility that uses Jasmine for its test syntax and can be run with Grunt. Writing UI tests in this environment is very similar to writing unit tests. For both you use the same syntax. As a result, tester and developer speak the same jargon so that knowledge can easily be shared.
Test Development
As mentioned in the beginning, our goal is to write UI tests that are easy to maintain. Let’s go through the following example:
With this test we check some user administration functionality in the Camunda Admin webapp. Although the test will exactly do what we expect, it contains some weaknesses:
– The tests are difficult to understand as they contain a lot of Protractor-specific expressions.
– The test logic and the page elements are closely coupled. Changes on the webapp GUI will have a huge impact on the test cases.
– With each test we duplicate code.
While the mentioned problems seem to be manageable, they will be multiplied with an increasing number of test cases. In the end, the test suite is difficult to maintain.
Fortunately, it is just a matter of code design to avoid the shown problem. To make our tests more robust against changes and to reduce code duplication we encapsulate all logic required to interact with the application under test into separate classes. This design pattern is called Page Object Pattern. As a result we get a clean separation between test logic and the page control logic as shown in the following snippet:
After this refactoring the test cases are much better to understand as every step has become more meaningful. Now the test is focused on the behavior of the application under test and the test specification is more comprehensive.
The corresponding page object looks like this:
By using page objects we decoupled the test from the page elements of the webapp, thus changes on the webapps GUI have no impact on the test case. Furthermore, you only need to adjust the test suite at single points in case of changes.
The outcome of this is a reduction of code duplication, as the page object can be reused wherever needed.
In addition to the page object that represents the page under test, we create a prototype page object. This prototype can be enriched with functionality that is available for all pages of the webapp:
Finally, we get a tidy test suite that is much easier to maintain in medium/long term.
Integrating Protractor into IntelliJ IDEA
Protractor can be integrated into the IntelliJ IDEA by installing the node.js plugin. That gives us the benefit to run and to debug tests directly in the IDE:
UI testing during webapp development
Running a huge automated UI test suite can take a while. So it is common to trigger these tests on your CI server over night to not slow down the build pipeline. This is perfect for regression testing but insufficient during the webapp development process. With the integration of Protractor into Grunt we can trigger single tests simply over the command line or directly in our IDE:
For that, we create specific profiles in the Grunt configuration file of our webapps as shown in the following image:
The test can also be triggered automatically after a change in the codebase. For this purpose we combine the grunt auto-build command with a protractor profile:
Conclusion
For an active codebase you need a flexible test suite. Writing tests in the described way allows you to separate test logic from page control logic so that high maintainability and better readability can be reached.
Protractor as test framework can easily be integrated in many setups, so that even changes in the technology stack only have a small impact on the test suite.
Last but not least, we decrease development time as we already get feedback from our UI tests during webapp development.
With IntelliJ IDEA we have a powerful IDE that allows us to build, run and debug UI tests. We thank JetBrains for the great support for our open source project.