A library that makes it easier to write high quality automated acceptance tests

Overview

Getting started with Serenity and Cucumber

Serenity BDD is a library that makes it easier to write high quality automated acceptance tests, with powerful reporting and living documentation features. It has strong support for both web testing with Selenium, and API testing using RestAssured.

Serenity strongly encourages good test automation design, and supports several design patterns, including classic Page Objects, the newer Lean Page Objects/ Action Classes approach, and the more sophisticated and flexible Screenplay pattern.

The latest version of Serenity supports Cucumber 6.x.

The starter project

The best place to start with Serenity and Cucumber is to clone or download the starter project on Github (https://github.com/serenity-bdd/serenity-cucumber-starter). This project gives you a basic project setup, along with some sample tests and supporting classes. There are two versions to choose from. The master branch uses a more classic approach, using action classes and lightweight page objects, whereas the screenplay branch shows the same sample test implemented using Screenplay.

The project directory structure

The project has build scripts for both Maven and Gradle, and follows the standard directory structure used in most Serenity projects:

src
  + main
  + test
    + java                        Test runners and supporting code
    + resources
      + features                  Feature files

    + search                  Feature file subdirectories

             search_by_keyword.feature

Serenity 2.2.13 introduced integration with WebdriverManager to download webdriver binaries.

The sample scenario

Both variations of the sample project uses the sample Cucumber scenario. In this scenario, Sergey (who likes to search for stuff) is performing a search on the internet:

Feature: Search by keyword

  Scenario: Searching for a term
    Given Sergey is researching things on the internet
    When he looks up "Cucumber"
    Then he should see information about "Cucumber"

The Screenplay implementation

The sample code in the master branch uses the Screenplay pattern. The Screenplay pattern describes tests in terms of actors and the tasks they perform. Tasks are represented as objects performed by an actor, rather than methods. This makes them more flexible and composable, at the cost of being a bit more wordy. Here is an example:

    @Given("{actor} is researching things on the internet")
    public void researchingThings(Actor actor) {
        actor.wasAbleTo(NavigateTo.theWikipediaHomePage());
    }

    @When("{actor} looks up {string}")
    public void searchesFor(Actor actor, String term) {
        actor.attemptsTo(
                LookForInformation.about(term)
        );
    }

    @Then("{actor} should see information about {string}")
    public void should_see_information_about(Actor actor, String term) {
        actor.attemptsTo(
                Ensure.that(WikipediaArticle.HEADING).hasText(term)
        );
    }

Screenplay classes emphasise reusable components and a very readable declarative style, whereas Lean Page Objects and Action Classes (that you can see further down) opt for a more imperative style.

The NavigateTo class is responsible for opening the Wikipedia home page:

public class NavigateTo {
    public static Performable theWikipediaHomePage() {
        return Task.where("{0} opens the Wikipedia home page",
                Open.browserOn().the(WikipediaHomePage.class));
    }
}

The LookForInformation class does the actual search:

public class LookForInformation {
    public static Performable about(String searchTerm) {
        return Task.where("{0} searches for '" + searchTerm + "'",
                Enter.theValue(searchTerm)
                        .into(SearchForm.SEARCH_FIELD)
                        .thenHit(Keys.ENTER)
        );
    }
}

In Screenplay, we keep track of locators in light weight page or component objects, like this one:

class SearchForm {
    static Target SEARCH_FIELD = Target.the("search field")
                                       .locatedBy("#searchInput");

}

The Screenplay DSL is rich and flexible, and well suited to teams working on large test automation projects with many team members, and who are reasonably comfortable with Java and design patterns.

The Action Classes implementation.

A more imperative-style implementation using the Action Classes pattern can be found in the action-classes branch. The glue code in this version looks this this:

    @Given("^(?:.*) is researching things on the internet")
    public void i_am_on_the_Wikipedia_home_page() {
        navigateTo.theHomePage();
    }

    @When("she/he looks up {string}")
    public void i_search_for(String term) {
        searchFor.term(term);
    }

    @Then("she/he should see information about {string}")
    public void all_the_result_titles_should_contain_the_word(String term) {
        assertThat(searchResult.displayed()).contains(term);
    }

These classes are declared using the Serenity @Steps annotation, shown below:

    @Steps
    NavigateTo navigateTo;

    @Steps
    SearchFor searchFor;

    @Steps
    SearchResult searchResult;

The @Stepsannotation tells Serenity to create a new instance of the class, and inject any other steps or page objects that this instance might need.

Each action class models a particular facet of user behaviour: navigating to a particular page, performing a search, or retrieving the results of a search. These classes are designed to be small and self-contained, which makes them more stable and easier to maintain.

The NavigateTo class is an example of a very simple action class. In a larger application, it might have some other methods related to high level navigation, but in our sample project, it just needs to open the DuckDuckGo home page:

public class NavigateTo {

    WikipediaHomePage homePage;

    @Step("Open the Wikipedia home page")
    public void theHomePage() {
        homePage.open();
    }
}

It does this using a standard Serenity Page Object. Page Objects are often very minimal, storing just the URL of the page itself:

@DefaultUrl("https://wikipedia.org")
public class WikipediaHomePage extends PageObject {}

The second class, SearchFor, is an interaction class. It needs to interact with the web page, and to enable this, we make the class extend the Serenity UIInteractionSteps. This gives the class full access to the powerful Serenity WebDriver API, including the $() method used below, which locates a web element using a By locator or an XPath or CSS expression:

public class SearchFor extends UIInteractionSteps {

    @Step("Search for term {0}")
    public void term(String term) {
        $(SearchForm.SEARCH_FIELD).clear();
        $(SearchForm.SEARCH_FIELD).sendKeys(term, Keys.ENTER);
    }
}

The SearchForm class is typical of a light-weight Page Object: it is responsible uniquely for locating elements on the page, and it does this by defining locators or occasionally by resolving web elements dynamically.

class SearchForm {
    static By SEARCH_FIELD = By.cssSelector("#searchInput");
}

The last step library class used in the step definition code is the SearchResult class. The job of this class is to query the web page, and retrieve a list of search results that we can use in the AssertJ assertion at the end of the test. This class also extends UIInteractionSteps and

public class SearchResult extends UIInteractionSteps {
    public String displayed() {
        return find(WikipediaArticle.HEADING).getText();
    }
}

The WikipediaArticle class is a lean Page Object that locates the article titles on the results page:

public class WikipediaArticle {
    public static final By HEADING =  By.id("firstHeading");
}

The main advantage of the approach used in this example is not in the lines of code written, although Serenity does reduce a lot of the boilerplate code that you would normally need to write in a web test. The real advantage is in the use of many small, stable classes, each of which focuses on a single job. This application of the Single Responsibility Principle goes a long way to making the test code more stable, easier to understand, and easier to maintain.

Executing the tests

To run the sample project, you can either just run the CucumberTestSuite test runner class, or run either mvn verify or gradle test from the command line.

By default, the tests will run using Chrome. You can run them in Firefox by overriding the driver system property, e.g.

$ mvn clean verify -Ddriver=firefox

Or

$ gradle clean test -Pdriver=firefox

The test results will be recorded in the target/site/serenity directory.

Generating the reports

Since the Serenity reports contain aggregate information about all of the tests, they are not generated after each individual test (as this would be extremenly inefficient). Rather, The Full Serenity reports are generated by the serenity-maven-plugin. You can trigger this by running mvn serenity:aggregate from the command line or from your IDE.

They reports are also integrated into the Maven build process: the following code in the pom.xml file causes the reports to be generated automatically once all the tests have completed when you run mvn verify?

             <plugin>
                <groupId>net.serenity-bdd.maven.plugins</groupId>
                <artifactId>serenity-maven-plugin</artifactId>
                <version>${serenity.maven.version}</version>
                <configuration>
                    <tags>${tags}</tags>
                </configuration>
                <executions>
                    <execution>
                        <id>serenity-reports</id>
                        <phase>post-integration-test</phase>
                        <goals>
                            <goal>aggregate</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

Simplified WebDriver configuration and other Serenity extras

The sample projects both use some Serenity features which make configuring the tests easier. In particular, Serenity uses the serenity.conf file in the src/test/resources directory to configure test execution options.

Webdriver configuration

The WebDriver configuration is managed entirely from this file, as illustrated below:

webdriver {
    driver = chrome
}
headless.mode = true

chrome.switches="""--start-maximized;--test-type;--no-sandbox;--ignore-certificate-errors;
                   --disable-popup-blocking;--disable-default-apps;--disable-extensions-file-access-check;
                   --incognito;--disable-infobars,--disable-gpu"""

Serenity uses WebDriverManager to download the WebDriver binaries automatically before the tests are executed.

Environment-specific configurations

We can also configure environment-specific properties and options, so that the tests can be run in different environments. Here, we configure three environments, dev, staging and prod, with different starting URLs for each:

environments {
  default {
    webdriver.base.url = "https://duckduckgo.com"
  }
  dev {
    webdriver.base.url = "https://duckduckgo.com/dev"
  }
  staging {
    webdriver.base.url = "https://duckduckgo.com/staging"
  }
  prod {
    webdriver.base.url = "https://duckduckgo.com/prod"
  }
}

You use the environment system property to determine which environment to run against. For example to run the tests in the staging environment, you could run:

$ mvn clean verify -Denvironment=staging

See this article for more details about this feature.

Want to learn more?

For more information about Serenity BDD, you can read the Serenity BDD Book, the official online Serenity documentation source. Other sources include:

You might also like...
A JUnit5 Platform TestEngine integrated with the official FHIR Validator to run profile and Questionnaire validation as tests.
A JUnit5 Platform TestEngine integrated with the official FHIR Validator to run profile and Questionnaire validation as tests.

🔥 FHIR Validator JUnit Engine A JUnit5 TestEngine to integrate the FHIR Validator into the JUnit5 ecosystem. Supports writing expected validation out

A collection of tests and easy to reuse pieces of code for bdk-jvm and bdk-android

Readme This repo is a collection of tests and easy to reuse pieces of code for bdk-jvm and bdk-android. Note that they don't aim to provide a full cov

Selenium locators for Java/Kotlin that resemble the Testing Library (testing-library.com).

Selenium Testing Library Testing Library selectors available as Selenium locators for Kotlin/Java. Why? When I use Selenium, I don't want to depend on

A multiplatform assertion library for Kotlin

Atrium is an open-source multiplatform assertion library for Kotlin with support for JVM, JS and Android. It is designed to support multiple APIs, dif

mocking library for Kotlin
mocking library for Kotlin

Kotlin Academy articles Check the series of articles "Mocking is not rocket science" at Kt. Academy describing MockK from the very basics of mocking u

Linkester is an Android library that aims to help Android developers test their deep links implementation.
Linkester is an Android library that aims to help Android developers test their deep links implementation.

Linkester Linkester is an Android library that aims to help Android developers test their deep links implementation. The idea is to have a new launche

Jitpack Library Tester

jitpack-library-test Repository for testing build from jitpack.io Red : Failed Green : Success / Pass Colaborator Very open to anyone, I'll write your

Strikt is an assertion library for Kotlin intended for use with a test runner such as JUnit, Minutest, Spek, or KotlinTest.

Strikt is an assertion library for Kotlin intended for use with a test runner such as JUnit, Minutest, Spek, or KotlinTest.

Turbine is a small testing library for kotlinx.coroutines Flow.

A small testing library for kotlinx.coroutines Flow

Owner
ricardo larrahondo
ricardo larrahondo
Automated tests using Rest-assured with Kotlin lang

Testes de API em Kotlin Pré-requisitos Instalar o Kotlin Ambiente Para executar os testes localmente, estou utilizando o ServeRest Link do Repo: https

Rafael Berçam 15 Dec 23, 2022
Espresso - Use Espresso to write concise, beautiful, and reliable Android UI tests

Espresso Use Espresso to write concise, beautiful, and reliable Android UI tests

Android For All 1 Jan 26, 2022
Write Tests as Examples on the Method-under-test

Write Tests as Examples on the Method-under-test

Paul Methfessel 1 Apr 12, 2022
Barista makes developing UI test faster, easier and more predictable. Built on top of Espresso

Barista makes developing UI test faster, easier and more predictable. Built on top of Espresso, it provides a simple and discoverable API, removing most of the boilerplate and verbosity of common Espresso tasks. You and your Android team will write tests with no effort.

Adevinta Spain 1.6k Jan 5, 2023
3 types of Tests in Android (Unit - instrumentation - UI)

UnitTestingPractice 3 types of Tests in Android Unit instrumentation (Integration) UI Unit Testing benefits confirm code work like a charm simulate Ap

Ahmed Tawfiq 8 Mar 23, 2022
Raccoon is a lightweight response mocking framework that can be easily integrated into the Android UI tests.

Raccoon Medium Articles Checkout these article to get more insights about this library: How to integrate this in your Android Test Why Raccoon? There

Joseph James 52 Aug 15, 2022
Easily scale your Android Instrumentation Tests across Firebase Test Lab with Flank.

Easily scale your Android Instrumentation Tests across Firebase Test Lab with Flank.

Nelson Osacky 220 Nov 29, 2022
Most popular Mocking framework for unit tests written in Java

Most popular mocking framework for Java Current version is 3.x Still on Mockito 1.x? See what's new in Mockito 2! Mockito 3 does not introduce any bre

mockito 13.6k Jan 4, 2023
Using grpc-wiremock to mock responses in integrated tests of gRPC services

Utilizando grpc-wiremock para mockar respostas em testes integrados de serviços gRPC Este repositório possui um exemplo prático de como configurar e r

Tony A. Luz 2 Oct 28, 2021
A simple project to help developers in writing their unit tests in Android Platform.

AndroidUnitTesting A simple project to help developers in writing their unit tests in Android Platform. This is not a multi-module project, but has th

Bruno Gabriel dos Santos 4 Nov 10, 2021