In my previous blog posts, we worked on achieving throughput via parallelism and making each test as reliable as possible.
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:
@Test
public void testWikipedia() {
driver().get("https://www.wikipedia.org/");
Thread.sleep(3000);
driver().findElement(By.id("searchInput")).sendKeys("WebDriver");
Thread.sleep(3000);
driver().findElements(By.className("suggestion-link")).get(0).click();
Thread.sleep(3000);
String title = driver().findElement(By.id("firstHeading")).getText();
Assert.assertEquals("Selenium (software)", title);
}
JavaIn 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:
public class MainPage extends WebPageObject {
@Override
public Optional < By > visibleBy() {
return Optional.of(Bys.INPUT);
}
public void search(String search) {
driver()
.augmented()
.findElementClickable(Bys.INPUT)
.sendKeys(search);
}
public WikiPage selectSuggestion(int index) {
driver()
.augmented()
.findElementsVisible(Bys.SUGGESTION)
.get(index)
.click();
return get(WikiPage.class);
}
public static class Bys {
public static final By INPUT = By.id("searchInput");
public static final By SUGGESTION = By.className("suggestion-link");
}
}
public class WikiPage extends WebPageObject {
@Override
public Optional < By > visibleBy() {
return Optional.of(Bys.TITLE);
}
public String getName() {
return driver().augmented().findElementVisible(Bys.TITLE).getText();
}
public static class Bys {
public static final By TITLE = By.id("firstHeading");
}
}
JavaAnd now our test looks like:
@Test
public void testWikiPedia() {
WikiPage wikiPage = mainPage()
.search("WebDriver")
.selectSuggestion(0);
Assert.assertEquals("Selenium (software)", wikiPage.getName());
}
private MainPage mainPage() {
driver().get("https://www.wikipedia.org/");
return get(MainPage.class);
}
JavaThe 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.
Get Split Certified
Split Arcade includes product explainer videos, clickable product tutorials, manipulatable code examples, and interactive challenges.
Switch It On With Split
The Split Feature Data Platform™ gives you the confidence to move fast without breaking things. Set up feature flags and safely deploy to production, controlling who sees which features and when. Connect every flag to contextual data, so you can know if your features are making things better or worse and act without hesitation. Effortlessly conduct feature experiments like A/B tests without slowing down. Whether you’re looking to increase your releases, to decrease your MTTR, or to ignite your dev team without burning them out–Split is both a feature management platform and partnership to revolutionize the way the work gets done. Switch on a free account today, schedule a demo, or contact us for further questions.