Keeping your automation tests clean

Keeping your automation tests clean

  • How many times have you started project for automation tests, and at the end end-up spending more time maintaining the automation tests, instead increasing the coverage?
  • How many times have you ended having duplicate code in multiple classes?
  • How many times have you had issues with the automation tests because they are dependent by each other?

Introduction

In this post I would talk about the architecture that I prefer to use when writing the automation tests, and it is going to help you solve the questions above. The architecture follows the Page Object Model (POM) pattern, in combination with Cucumber and Selenium. The sample project that I’m going to introduce in this post is going to help you when writing the automation tests.

The solution

The logic behind this approach is to have the code separated in Java/src folder and the tests folder. In the Java/src are going to be stored the classes of the Page objects, Driver handling, Configuration reading, etc. In the tests folder are going to be stored the step definitions of the scenarios in the feature file, the feature files itself, and the runner class for running the scenarios. On the following image is described the separation of the code.

Project structure.

Page classes

First I’m going to start with the page classes which are responsible for the interaction of the UI elements. Each page class inherits the BasePage, and through the ElementAllocator are retrieved the WebElements that have to be interacted with. This approach helps to minimize the boilerplate code in your tests, and increase the readability of your tests. Here is an example of one page class:

public class AboutPage extends BasePage {

    public AboutPage(){
        super();
    }

    @Override
    public void open() {
        WebElement aboutButton = 
        elementAllocator.getElementVisible(
        By.xpath("//nav[@id = 'access']//li//a[text() = 'About']"), 
        ElementAllocator.WAIT_BY_CONFIGURATION);
        aboutButton.click();
    }
}

The ElementAllocator helps to locate the UI elements on the page when they are present in the DOM or visible to the end user. When using the method that ends with “Visible” is going to wait for the element to be visible for the end user, and when using the method that ends with “Present” is going to wait for the element to be present in the DOM.

If your web page requires more advanced UI interaction, then this interaction has to be defined in the ElementAllocator class, and later implemented in the method that requires the more advanced interaction.

Scenario cycle

The scenario cycle is important because it handles the following actions:

  • Initialization of the WebDriver.
  • Navigating to the application for testing.
  • Capturing screenshots after finishing the scenario.
  • Executing the step for reseting the scenario data once the scenario is finished.
  • Destroying the WebDriver once the scenarios are finished with the execution.

The WebDriver initialization is done through the DriverManager class. This class is responsible to initialize the WebDriver according to the set value in the automation.properties file. Currently the implemented drivers is Chrome and Headless Chrome.

Once the WebDriver is initialized the next step of the cycle is navigating to the web application on which the automation tests are going to be run. The instance of the application is read from the automation.properties file, which allows the tester to focus implementing the business logic of the automation scenarios.

If the scenario for some instance fails, then in this case screenshot is taken from the web application, and log from the browser console. This information is going to helpful for the tester to determine the root cause of the failed test, and determine whether is flaky test or bug in the application. The path of the screenshot and the browser is configurable, and it could be set in the automation.properties file.

The automation framework allows the tester to define step which is going to be executed once the scenario is finished, and these kind of the steps are handy if the tester needs to reset the data of the scenario. This step allows to execute DB query or perform some steps in the web application for reseting the data. When using DB queries to reset the data is going to make the tests faster, on the other hand when reseting the scenario data through the UI elements is going to extend the duration of the automation test suite.

This framework destroys the WebDriver automatically when the tests are executed.

Why additional step for reseting the scenario

This step is helpful when the testers needs to reset the scenario data, so that test scenarios is independent for each run of the automation suite. In this automation framework this is done by setting the reset step through a Given step in the scenario. Here is an example how the reset step is defined through the Given step in the feature file.

Given The step for resetting the scenario data

But just giving descriptive name for the Given reset step scenario is not enough. The step definition has to be implemented, and that is done in the following way:

@Given("^The step for resetting the scenario data$")
public void givenTheStepForResettingTheScenarioData(){
    scenarioResetStepHandler.addScenarioDataResetStepAction(
    new ScenarioDataReset() {
        public void onScenarioDataResetStepAction() {
            System.out.println("The scenario data is reset.");
        }
    });
}

The reset step for the scenario is done by the ScenarioResetStepHandler, by which is added the ScenarioDataReset interface. The ScenarioResetStepHandler allows the automation tester to add several steps for reseting the scenario. The step for reseting the scenario is not executed immediately in the Given step, but it is executed once the scenario has finished with the last defined step in the feature file. This way the framework ensures each scenario in the automation suite to be independent.

Final thoughts

This is just one example how to structure you project for you automation, but depending from project to project, the structure of the project might be slightly different. The world would be much boring if everything was the same, and we would had to implement the same old solution 😀 I hope this post was helpful for you, and had brought some new interesting ideas with you automation.

 

One thought on “Keeping your automation tests clean

  1. Pingback: Testing Bits – June 24th – June 30th, 2018 | Testing Curator Blog

Leave a Reply

Your email address will not be published. Required fields are marked *