The next missing piece in the puzzle is related to modularity and reusability. We are living in a world of Continuous Integration and Continuous Delivery, so we want our framework to be extended easily and quickly adapt to changes in the application being tested.
That leads us to our next lesson:
Follow the Page Object Model.
This topic has been extensively discussed in the Selenium world, but as a brief summary, Page Object Design Pattern helps when modeling your application. Each “page” of your application (whether it is a Web App or Mobile App) is encapsulated into one class, and all the possible interactions on that application component are implemented there.
When done right, these objects can be reused across all your test suites. With that high level of abstraction, you can adapt your tests to changes on your underlying application with little effort.
As an example, let’s work on Wikipedia. A test that searches for a topic and goes to that page might look like:
In the example above, the test first browses to Wikipedia, then searches for “WebDriver”, goes to the first result and finally asserts that the title of the landing page is “Selenium (software)”.
In this scenario, besides the poorly managed timing criteria used (check out this blog post on how to deal with it), we are facing another painful problem:
There is no separation between the test and the application being tested.
As a result, when extending our coverage, we start duplicating code in the different tests. If at one point, for example, the locator of the search button changes, we have to go through all the tests using that functionality to apply the new locator. This approach quickly becomes unmanageable.
In the AugmentedDriver world, we can define Page Objects:
And now our test looks like:
The only requirement of a WebPageObject is that you need to implement the method visibleBy(). The framework won’t instantiate the object until that By is visible. This helps significantly with reliability, since the AugmentedDriver will wait until the application is in the right state before the test can continue.
With this approach, there is a clear separation of the test and the business logic of your application. Locators are defined once inside the Page Object Class, greatly reducing the effort of adapting the tests to changes. New functionality can also be added inside the Page Object Class and immediately reused on any other test, reducing code duplication and accelerating the development of new tests.
In summary, as part of a Continuous Integration ecosystem, your UI Automation Tests should be able to adapt quickly to changes. By following the Page Object Model, tests and business logic are pulled apart from each other; Easing up not only on the maintainability effort, but also reducing the time spent on covering new functionality.