Fluent Wait in Serenity

HOME

In the previous tutorials, I explained the Implicit Wait in Serenity and Explicit Wait in Serenity. This tutorial will explain the Fluent Wait in Serenity.

What is Fluent Wait?

Fluent waits provide more flexibility, allowing us to specify polling intervals and ignore specific exceptions during the wait time.  Fluent Wait not only lets you specify the maximum amount of time to wait for a condition but also allows you to define the frequency with which the condition is checked and to ignore specific exceptions during the wait time.

Below is the example of Fluent wait.

import net.serenitybdd.annotations.DefaultUrl;
import net.serenitybdd.annotations.Managed;
import net.serenitybdd.core.annotations.findby.FindBy;
import net.serenitybdd.core.pages.PageObject;
import net.serenitybdd.core.pages.WebElementFacade;
import net.serenitybdd.junit.runners.SerenityRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openqa.selenium.ElementNotInteractableException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.FluentWait;

import java.time.Duration;
import java.util.function.Function;

@RunWith(SerenityRunner.class)
@DefaultUrl("http://the-internet.herokuapp.com/dynamic_loading/1")
public class FluentWait_Demo extends PageObject {

    @Managed
    WebDriver driver;

    @FindBy(xpath = "//*[@id='start']/button")
    WebElementFacade startButton;


    @FindBy(xpath = "//*[@id='finish']/h4")
    WebElementFacade pageText;

    @Test
    public void fluentWaitDemo() throws InterruptedException {

        open();
        startButton.click();
        waitForElementWithFluentWait(pageText);

    }

    public void waitForElementWithFluentWait(WebElement pageText) {
        FluentWait wait = new FluentWait<>(getDriver())
                .withTimeout(Duration.ofSeconds(10))
                .pollingEvery(Duration.ofSeconds(2))
                .ignoring(ElementNotInteractableException.class);

        wait.until((Function<WebDriver, Boolean>)
                driver -> pageText.isDisplayed());

        System.out.println("Text :" + pageText.getText());
        System.out.println("Fluent Time defined for the test (in seconds) :" + getWaitForTimeout().toSeconds());
    }
}

public void waitForElementWithFluentWait(WebElement pageText) {
        FluentWait wait = new FluentWait<>(getDriver())
                .withTimeout(Duration.ofSeconds(10))
                .pollingEvery(Duration.ofSeconds(2))
                .ignoring(ElementNotInteractableException.class);

       wait.until(driver -> pageText.isDisplayed());

        System.out.println("Text :" + pageText.getText());
        System.out.println("Fluent Time defined for the test (in seconds) :" + getWaitForTimeout().toSeconds());
    }

We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

Testing of Web Application using Serenity with JUnit5

Last Updated On

HOME

In the previous tutorial, I explained about the Testing of Web Application using Serenity with JUnit4. In this tutorial, I’ll explain the Integration of Serenity BDD with JUnit5.

Table Of Contents

  1. Prerequisite
  2. Dependency List
  3. Structure of Project
  4. Implementation Steps
    1. Update Properties section in Maven pom.xml
    2. Add Serenity and JUnit dependencies to POM.xml
    3. Update Build Section of pom.xml
    4. Create Test Class sunder src/test/java folder
    5. Create serenity.conf file under src/test/resources
    6. Create serenity.properties file at the root of the project
    7. Run the tests through the command line
    8. Serenity Report Generation

Prerequisite

  1. Java 17 installed
  2. Maven installed
  3. Eclipse or IntelliJ installed

Dependency List:

  1. Java 17
  2. Maven – 3.9.9
  3. Serenity – 4.0.30
  4. Serenity JUnit5 – 4.0.30
  5. JUnit5 – 5.11.0
  6. Maven Surefire Plugin – 3.5.0
  7. Maven Failsafe Plugin – 3.5.0
  8. Maven Compiler Plugin – 3.13.0

Structure of Project

Implementation Steps

Step 1 – Update Properties section in Maven pom.xml

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <serenity.version>4.0.30</serenity.version>
    <junit5.version>5.11.0</junit5.version>
    <maven.surefire.plugin.version>3.5.0</maven.surefire.plugin.version>
    <maven.failsafe.plugin.version>3.5.0</maven.failsafe.plugin.version>
    <maven.compiler.plugin.version>3.13.0</maven.compiler.plugin.version>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
    <encoding>UTF-8</encoding>
    <tags></tags>
    <webdriver.base.url></webdriver.base.url>
</properties>

Step 2 – Add Serenity and JUnit dependencies to POM.xml

<dependencies>

    <dependency>
      <groupId>net.serenity-bdd</groupId>
      <artifactId>serenity-core</artifactId>
      <version>${serenity.version}</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>net.serenity-bdd</groupId>
      <artifactId>serenity-junit5</artifactId>
      <version>${serenity.version}</version>
      <scope>test</scope>
    </dependency>

    <!-- JUNIT 5 DEPENDENCY-->
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <version>${junit5.version}</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-engine</artifactId>
      <version>${junit5.version}</version>
      <scope>test</scope>
    </dependency>

    <!-- Assertj -->
    <dependency>
      <groupId>org.assertj</groupId>
      <artifactId>assertj-core</artifactId>
      <version>${assertj.version}</version>
      <scope>test</scope>
    </dependency>
    
</dependencies>

Step 3 – Update Build Section of pom.xml

 <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>${maven.surefire.plugin.version}</version>
        <configuration>
          <skip>false</skip>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-failsafe-plugin</artifactId>
        <version>${maven.failsafe.plugin.version}</version>
        <configuration>
          <includes>
            <include>**/*Test.java</include>
            <include>**/Tests.java</include>
            <include>**/*TestSuite.java</include>
            <include>**/When*.java</include>
          </includes>
          <systemPropertyVariables>
            <webdriver.base.url>${webdriver.base.url}</webdriver.base.url>
            <junit.jupiter.extensions.autodetection.enabled>true</junit.jupiter.extensions.autodetection.enabled>
          </systemPropertyVariables>
        </configuration>
        <executions>
          <execution>
            <goals>
              <goal>integration-test</goal>
              <goal>verify</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>${maven.compiler.plugin.version}</version>
        <configuration>
          <source>${maven.compiler.source}</source>
          <target>${maven.compiler.target}</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>net.serenity-bdd.maven.plugins</groupId>
        <artifactId>serenity-maven-plugin</artifactId>
        <version>${serenity.version}</version>
        <configuration>
          <tags>${tags}</tags>
          <reports>single-page-html</reports>
        </configuration>
        <executions>
          <execution>
            <id>serenity-reports</id>
            <phase>post-integration-test</phase>
            <goals>
              <goal>aggregate</goal>
            </goals>
          </execution>
        </executions>
        <dependencies>
          <dependency>
            <groupId>net.serenity-bdd</groupId>
            <artifactId>serenity-single-page-report</artifactId>
            <version>${serenity.version}</version>
          </dependency>
        </dependencies>
      </plugin>
    </plugins>
  </build>

Step 4 – Create the Test Class sunder src/test/java folder

ApplicationLoginJUnit5Tests.java

import com.example.steps.StepDashboardPage;
import com.example.steps.StepForgetPasswordPage;
import com.example.steps.StepLoginPage;
import net.serenitybdd.annotations.Steps;
import net.serenitybdd.annotations.Title;
import net.serenitybdd.core.Serenity;
import net.serenitybdd.junit5.SerenityJUnit5Extension;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

import static org.assertj.core.api.Assertions.assertThat;

@ExtendWith(SerenityJUnit5Extension.class)
public class ApplicationLoginTests {

    @Steps
    NavigateActions navigate;

    @Steps
    StepLoginPage loginPage;

    @Steps
    StepDashboardPage dashboardPage;

    @Steps
    StepForgetPasswordPage forgetPasswordPage;

    @Test
    @Title("Login to application with valid credentials navigates to DashBoard page")

    public void successfulLogin() {

        navigate.toTheHomePage();

        // When
        loginPage.inputUserName("Admin");
        loginPage.inputPassword("admin123");
        loginPage.clickLogin();

        // Then
        Serenity.reportThat("Passing valid credentials navigates to DashBoard page",
                () -> assertThat(dashboardPage.getHeading()).isEqualToIgnoringCase("Dashboard"));
    }

    @Test
    @Title("Login to application with invalid credential generates error message")
    void unsuccessfulLogin() {

        navigate.toTheHomePage();

        // When
        loginPage.inputUserName("Admin");
        loginPage.inputPassword("admin1232");
        loginPage.clickLogin();

        // Then
        Serenity.reportThat("Passing invalid credentials generates error message",
                () -> assertThat(loginPage.loginPageErrorMessage()).isEqualToIgnoringCase("Invalid credentials"));
    }

    @Test
    @Title("Verify Forgot your password link")
    void clickForgetPasswordLink() {

        // Given
        navigate.toTheHomePage();

        // When
        loginPage.clickForgetPasswordLink();

        // Then
        Serenity.reportThat("Open Forget Password Page after clicking forget password link",
                () -> assertThat(forgetPasswordPage.getHeadingForgetPasswordPage())
                        .isEqualToIgnoringCase("Reset Password"));
    }
}

To run a JUnit5 test with Serenity BDD, simply add the annotation @net.serenitybdd.junit5.SerenityTest (instead of @org.junit.runner.RunWith(net.serenitybdd.junit.runners.SerenityRunner.class) for JUnit4.

@ExtendWith(SerenityJUnit5Extension.class)

@Test is imported from package:-

import org.junit.jupiter.api.Test;

StepDashboardPage

import net.serenitybdd.annotations.Step;

import net.serenitybdd.core.pages.PageObject;
import net.serenitybdd.core.pages.WebElementFacade;
import org.openqa.selenium.support.FindBy;

public class StepDashboardPage extends PageObject {

    @FindBy(xpath = "//*[@class='oxd-topbar-header-breadcrumb']/h6")
    WebElementFacade dashboardPageTitle;

    @Step("Heading of DashBoard Page")
    public String getHeading() {
        return dashboardPageTitle.getText();
    }
}

StepForgetPasswordPage

import net.serenitybdd.annotations.Step;

import net.serenitybdd.core.pages.PageObject;
import net.serenitybdd.core.pages.WebElementFacade;
import org.openqa.selenium.support.FindBy;

public class StepForgetPasswordPage extends PageObject {

    @FindBy(xpath = "//*[@class='oxd-form']/h6")
    WebElementFacade forgetLink;

    @Step("Verify Forget Password Page ")
    public String getHeadingForgetPasswordPage() {
        return forgetLink.getText();
    }
}

StepLoginPage

package com.example.steps;

import net.serenitybdd.annotations.Step;

import net.serenitybdd.core.pages.PageObject;
import net.serenitybdd.core.pages.WebElementFacade;
import org.openqa.selenium.support.FindBy;

public class StepLoginPage extends PageObject {

    @FindBy(name = "username")
    WebElementFacade username;

    @FindBy(name = "password")
    WebElementFacade password;

    @FindBy(xpath = "//*[@class='oxd-form']/div[3]/button")
    WebElementFacade submitButton;

    @FindBy(xpath = "//*[@class='orangehrm-login-error']/div/div/p")
    WebElementFacade errorMessage;

    @FindBy(xpath = "//*[@class='orangehrm-login-forgot']/p")
    WebElementFacade forgotPasswordLinkText;

    @Step("Enter Username")
    public void inputUserName(String userName) {
        username.sendKeys(userName);
    }

    @Step("Enter Password")
    public void inputPassword(String passWord) {
        password.sendKeys(passWord);
    }

    @Step("Click Submit Button")
    public void clickLogin() {
        submitButton.click();
    }

    @Step("Error Message on unsuccessful login")
    public String loginPageErrorMessage() {
        return errorMessage.getText();
    }

    @Step("Click Forget Password Link")
    public void clickForgetPasswordLink() {
        forgotPasswordLinkText.click();
    }
}

The WebElementFacade class contains a convenient fluent API for dealing with web elements, providing some commonly-used extra features that are not provided out-of-the-box by the WebDriver API. WebElementFacades are largely interchangeable with WebElements: you just declare a variable of type WebElementFacade instead of type WebElement

The @Steps annotation marks a Serenity step library.
Create the test following the Given/When/Then pattern and using step methods from the step library.
The @Title annotation lets you provide your own title for this test in the test reports. Serenity @Title is considered for the Serenity report. Consistently with Junit4, the @Title annotation does not influence the name in the Junit report.

The JUnit Serenity integration provides some special support for Serenity Page Objects. In particular, Serenity will automatically instantiate any PageObject fields in your JUnit test.

Junit5 @Disabled annotation can be used on test and step methods(same as @Ignore in JUnit4).

import net.serenitybdd.annotations.Step;
import net.serenitybdd.core.steps.UIInteractionSteps;

public class NavigateAction extends UIInteractionSteps {

    @Step
    public void toTheHomePage() {
        openPageNamed("loginForm");
       
    }
}

Step 5 – Create serenity.conf file under src/test/resources

serenity.conf file is used to specify various features like the type of web driver used, various test environments, run tests in headless mode, and many more options.

pages{
   loginForm ="https://opensource-demo.orangehrmlive.com/"
   }

webdriver {
  driver = chrome
  capabilities {
    browserName = "chrome"
    acceptInsecureCerts = true
    "goog:chromeOptions" {
      args = ["remote-allow-origins=*","test-type", "no-sandbox", "ignore-certificate-errors", "--window-size=1920,1080",
        "incognito", "disable-infobars", "disable-gpu", "disable-default-apps", "disable-popup-blocking",
        "disable-dev-shm-usage", "disable-extensions", "disable-web-security", "disable-translate", "disable-logging"]
    }
  }
}

Step 6 – Create serenity.properties file at the root of the project

serenity.project.name = Serenity and JUnit5 Demo

Step 7 – Run the tests through the command line

Execute the tests through the command line by using the below command

mvn clean verify

The output of the above test execution is

Step 8 – Serenity Report Generation

The path of Serenity’s reports is mentioned in the image. The reports are generated under /target/site/serenity/.

Index.html

The detailed steps of the tests can also be viewed in the Serenity Report. It shows the execution time of all the steps in a Test.

Serenity-Summary.html

We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

Additional Tutorials:

 Serenity BDD with Cucumber for Web Application
Serenity BDD with Cucumber for SpringBoot Application
Serenity BDD with Cucumber and Rest Assured
Testing of SpringBoot REST Application using Rest Assured for GET Method
Serenity Report for Web Application with Cucumber6 and Junit
How to manage screenshots in Serenity Report

Testing of Web Application using Serenity with JUnit4

HOME

In the previous tutorial, I explained Serenity BDD with Cucumber for Web Application. In this tutorial, I will explain the Integration of Serenity with JUnit4. This tutorial gives an idea of how to set up a new project where we like to use Serenity as BDD Framework and JUnit as a Testing framework.

Prerequisite

  1. Java 17 installed
  2. Maven installed
  3. Eclipse or IntelliJ installed

Dependency List:

  1. Java 17
  2. Maven – 3.9.9
  3. Serenity – 4.0.30
  4. JUnit – 4.13.2
  5. Maven Surefire Plugin – 3.2.3
  6. Maven Failsafe Plugin – 3.2.3
  7. Maven Compiler Plugin – 3.12.1

Project Structure

This project consists of various classes – ApplicationLoginTests (This is the Test Class which is going to contain all the tests). NavigationActions is the Action class that is used to open the webpage or application. StepLoginPage, StepDashboardPage, and StepForgotPasswordPage are the Page Object classes that contain multiple functionalities of that page and that help to keep the code clean.

Step 1 – Update the Properties section

 <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <serenity.version>4.0.30</serenity.version>
    <junit.version>4.13.2</junit.version>
    <maven.compiler.plugin.version>3.12.1</maven.compiler.plugin.version>
    <maven.surefire.plugin.version>3.2.3</maven.surefire.plugin.version>
    <maven.failsafe.plugin.version>3.2.3</maven.failsafe.plugin.version>
    <maven.compiler.source.version>17</maven.compiler.source.version>
    <maven.compiler.target.version>17</maven.compiler.target.version>
    <tags></tags>
    <parallel.tests></parallel.tests>
    <webdriver.base.url></webdriver.base.url>
  </properties>

Step 2 – Add dependencies to POM.xml

<dependencies>
   <dependency>
            <groupId>net.serenity-bdd</groupId>
            <artifactId>serenity-core</artifactId>
            <version>${serenity.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>net.serenity-bdd</groupId>
            <artifactId>serenity-junit</artifactId>
            <version>${serenity.version}</version>
            <scope>test</scope>
        </dependency>
      
        <dependency>
            <groupId>net.serenity-bdd</groupId>
            <artifactId>serenity-screenplay</artifactId>
            <version>${serenity.version}</version>
            <scope>test</scope>
        </dependency>
      
        <dependency>
            <groupId>net.serenity-bdd</groupId>
            <artifactId>serenity-screenplay-webdriver</artifactId>
            <version>${serenity.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>      
</dependencies>

Step 3 – Update the Build Section of pom.xml

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>${maven.surefire.plugin.version}</version>
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>${maven.failsafe.plugin.version}</version>
                <configuration>
                    <includes>
                        <include>**/*.java</include>
                    </includes>
                    <parallel>methods</parallel>
                    <useUnlimitedThreads>true</useUnlimitedThreads>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven.compiler.plugin.version}</version>
                <configuration>
                    <source>${maven.compiler.source}</source>
                    <target>${maven.compiler.target}</target>
                </configuration>
            </plugin>
           <plugin>
               <groupId>net.serenity-bdd.maven.plugins</groupId>
               <artifactId>serenity-maven-plugin</artifactId>
               <version>${serenity.version}</version>
               <dependencies> 
                  <dependency>
                       <groupId>net.serenity-bdd</groupId>
                       <artifactId>serenity-single-page-report</artifactId>
                       <version>${serenity.version}</version>
                  </dependency>                
               </dependencies>
               <configuration>
                   <tags>${tags}</tags>
                   <reports>single-page-html</reports> 
               </configuration>
               <executions>
                  <execution>
                      <id>serenity-reports</id>
                      <phase>post-integration-test</phase>
                      <goals>
                          <goal>aggregate</goal>
                      </goals>
                   </execution>
               </executions>
           </plugin>
        </plugins>
    </build>
</project>

Step 4 – Create the Test Class

package org.example.tests;

import net.serenitybdd.annotations.Pending;
import net.serenitybdd.annotations.Steps;
import net.serenitybdd.annotations.Title;
import net.serenitybdd.core.Serenity;
import net.serenitybdd.junit.runners.SerenityRunner;
import org.example.steps.StepDashBoardPage;
import org.example.steps.StepForgotPasswordPage;
import org.example.steps.StepLoginPage;
import org.junit.Test;
import org.junit.runner.RunWith;

import static org.junit.Assert.assertTrue;

@RunWith(SerenityRunner.class)
public class ApplicationLoginTests {

    @Steps
    NavigateActions navigate;

    @Steps
    StepLoginPage loginPage;

    @Steps
    StepDashBoardPage dashboardPage;

    @Steps
    StepForgotPasswordPage forgetPasswordPage;


    @Test
    @Title("Login to application with invalid credential generates error message")
    public void invalidCredentials() {

        // Given
        navigate.toTheHomePage();

        // When
        loginPage.inputUserName("Admin");
        loginPage.inputPassword("admin");
        loginPage.clickLogin();

        // Then
        Serenity.reportThat("Passing invalid credentials generates error message",
                () -> assertTrue(loginPage.errorMessage().equalsIgnoreCase("Invalid Credentials")));

    }

    @Test
    @Title("Login to application with valid credentials navigates to DashBoard page")
    public void successfulLogin() {

        navigate.toTheHomePage();
        // loginPage.open();

        // When
        loginPage.inputUserName("Admin");
        loginPage.inputPassword("admin123");
        loginPage.clickLogin();

        // Then
        Serenity.reportThat("Passing valid credentials navigates to DashBoard page",
                () -> assertTrue(dashboardPage.getHeading().equalsIgnoreCase("DashBoard")));
    }


    @Test
    @Pending
    @Title("Verify Forgot your password link")
    public void clickForgetPasswordLink() {

        // Given
        navigate.toTheHomePage();

        // When
        loginPage.clickForgetPasswordLink();

        // Then
        Serenity.reportThat("Open Forget Password Page after clicking forget password link",
                () -> assertTrue(forgetPasswordPage.getHeadingForgetPasswordPage().equalsIgnoreCase("Reset Password")));

    }

}
  1. The tests run using the Serenity test runner – @RunWith(SerenityRunner.class).
  2. The @Steps annotation marks a Serenity step library.
  3. Create the test following the Given/When/Then pattern and using step methods from the step library.
  4. The @Title annotation lets you provide your own title for this test in the test reports.

Step 5 – Create the Action class

Create NavigateActions class under src/test/java. This class is used to open a web browser with the URL specified. This class is extended from UIInteractionSteps.

openPageNamed() method opens an environment-specific page defined in the serenity.conf file under the pages section. The value of loginForm is derived from serenity.config:

package org.example.tests;

import net.serenitybdd.annotations.Step;
import net.serenitybdd.core.steps.UIInteractionSteps;

public class NavigateActions extends UIInteractionSteps {

    @Step
    public void toTheHomePage() {
        // openUrl("https://opensource-demo.orangehrmlive.com/");

        openPageNamed("loginForm");
    }
}

serenity.conf (partial config file)

pages{
  loginForm = "https://opensource-demo.orangehrmlive.com/"
  }

Step 6 – Create the Page Object Classes

StepLoginPage

package org.example.steps;

import net.serenitybdd.annotations.Step;
import net.serenitybdd.core.pages.PageObject;
import net.serenitybdd.core.pages.WebElementFacade;
import org.openqa.selenium.support.FindBy;

public class StepLoginPage extends PageObject {

    @FindBy(name = "username")
    WebElementFacade username;

    @FindBy(name = "password")
    WebElementFacade password;

    @FindBy(xpath = "//*[@class='oxd-form']/div[3]/button")
    WebElementFacade submitButton;

    @FindBy(xpath = "//*[@class='orangehrm-login-error']/div/div/p")
    WebElementFacade errorMessage;

    @FindBy(xpath = "//*[@class='orangehrm-login-forgot']/p")
    WebElementFacade linkText;

    @Step("Enter Username")
    public void inputUserName(String userName) {
        username.sendKeys(userName);
    }

    @Step("Enter Password")
    public void inputPassword(String passWord) {
        password.sendKeys(passWord);
    }

    @Step("Click Submit Button")
    public void clickLogin() {
        submitButton.click();
    }

    @Step("Error Message on unsuccessful login")
    public String errorMessage() {
        String actualErrorMessage = errorMessage.getText();
        return actualErrorMessage;
    }

    @Step("Click Forget Password Link")
    public void clickForgetPasswordLink() {
        linkText.click();

        System.out.println("Clicked on Forgot Password Link");
    }

}

StepDashBoardPage

package org.example.steps;

import net.serenitybdd.annotations.Step;
import net.serenitybdd.core.pages.PageObject;
import net.serenitybdd.core.pages.WebElementFacade;
import org.openqa.selenium.support.FindBy;

public class StepDashBoardPage extends PageObject {

    @FindBy(xpath = "//*[@class='oxd-topbar-header-breadcrumb']/h6")
    WebElementFacade dashboardPageTitle;

    @Step("Heading of DashBoard Page")
    public String getHeading() {
        return dashboardPageTitle.getText();


    }
}

StepForgetPasswordPage

package org.example.steps;

import net.serenitybdd.annotations.Step;
import net.serenitybdd.core.pages.PageObject;
import net.serenitybdd.core.pages.WebElementFacade;
import org.openqa.selenium.support.FindBy;

public class StepForgotPasswordPage extends PageObject {

    @FindBy(xpath = "//*[@class='oxd-form']/h6")
    WebElementFacade forgetLink;


    @Step("Verify Forget Password Page ")
    public String getHeadingForgetPasswordPage() {

        return forgetLink.getText();
    }
}

Keep in mind to use @FindBy annotation from:

import org.openqa.selenium.support.FindBy;

PageObject class is imported from:

import net.thucydides.core.pages.PageObject;

The JUnit Serenity integration provides some special support for Serenity Page Objects. In particular, Serenity will automatically instantiate any PageObject fields in the JUnit test. When a field of type StepLoginPage is declared in the test, Serenity instantiates it for you. The page is automatically instantiated and ready to be used.

@Managed                                                                
WebDriver driver;

@Managed declares a WebDriver instance that will be managed by Serenity. The WebDriver instance will be initialized automatically.

The driver parameter lets you define what WebDriver driver you want to run these tests in. Possible values include Firefox, chrome, iexplorer, phantomjs, appium, safari, edge, and htmlunit.  The default browser in Serenity is Firefox. There are multiple ways to configure webDriver. One of the ways is to mention with @Managed as shown below:

@Managed(driver="chrome")

Step 7 – Create the serenity.conf file

Serenity.conf file is used to specify various features like the type of webdriver used, various test environments, run test in headless mode, and many more options. Serenity.conf can also contain settings like start size, disable sandbox, disable gpu, and others that need to be added to chrome.switches setting. Create serenity.conf file under src/test/resources.

headless.mode = false
pages{
   loginForm ="https://opensource-demo.orangehrmlive.com/"
   }

webdriver {
  driver = chrome
  capabilities {
    browserName = "chrome"
    acceptInsecureCerts = true
    "goog:chromeOptions" {
      args = ["remote-allow-origins=*","test-type", "no-sandbox", "ignore-certificate-errors", "--window-size=1920,1080",
        "incognito", "disable-infobars", "disable-gpu", "disable-default-apps", "disable-popup-blocking",
        "disable-dev-shm-usage", "disable-extensions", "disable-web-security", "disable-translate", "disable-logging"]
    }
  }
}

Step 8 – Create a serenity.properties file

serenity.project.name = Serenity and Junit4 Demo

Step 9 – Run the tests through the command

Open the command line and go to the location where the pom.xml of the project is present and type the below command.

mvn clean verify

Below is the execution status.

There are 2 types of reports are generated – Index.html and Serenity-Summary.html.

Index.html

 We can see the value of the @Title annotation, ‘Login to the application with valid credentials navigates to DashBoard page’, added as the heading. The value of @Step annotation, ‘Enter Username’, and ‘Enter Password’ is added to the Report as various steps.

This report contains a screenshot of each step also.

Emailable Report (Serenity-Summary.html)

These reports are present under /target/site/serenity.

Skipping the tests

In Serenity, you use the @Pending annotation, either for a test or for a @Step-annotated method, to indicate that the scenario is still being implemented and that the results are not available yet. These tests appear as ‘Pending’ (shown in blue) in the test reports.

    @Test
	@Pending
	@Title("Verify Forgot your password link")
	public void clickForgetPasswordLink() {

		// Given
		loginPage.open();

		// When
		loginPage.clickForgetPasswordLink();

		// Then
		Assert.assertTrue(forgetpasswordPage.ForgetPasswordPage());
	}

Tests marked with @Ignore will appear as ‘Ignored’ (from JUnit) and appears as grey in the test reports.

We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

SpringBoot Tutorials

 

HOME

Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can “just run”. We take an opinionated view of the Spring platform and third-party libraries, so you can get started with minimum fuss. Most Spring Boot applications need minimal Spring configuration.

Chapter 1 Create your first SpringBoot application in IntelliJ
Chapter 2 SpringBoot Integration Test
Chapter 3 Integration Testing of Springboot with RestAssured
Chapter 4 Testing of SpringBoot REST Application using Serenity BDD and Rest Assured for GET Method
Chapter 5 Testing of SpringBoot REST Application using Serenity BDD and Rest Assured for POST Method to create a Resource
Chapter 6 Testing of SpringBoot REST Application using Serenity BDD and Rest Assured for PUT Method to update a Resource
Chapter 7 Testing of SpringBoot REST Application using Serenity BDD and Rest Assured for DELETE Method to delete a Resource
Chapter 8 Testing of SpringBoot Validation for RESTful Services
Chapter 9 Testing of SpringBoot Exception Handling
Chapter 10 SpringBoot WireMock
Chapter 11 SpringBoot Dependency Injection using Autowired

SpringBoot Testing with JUnit

Chapter 1 Integration Testing of Springboot with Cucumber and JUnit4
Chapter 2 Integration Testing of SpringBoot Application with Serenity BDD, Cucumber and JUnit4
Chapter 3 Testing of SpringBoot Application with Serenity and JUnit5
Chapter 4 Testing of SpringBoot Application with Serenity BDD, Cucumber and JUnit5
Chapter 5 Testing of SpringBoot Application with JUnit5

SpringBoot with TestNG

Chapter 1 Testing of SpringBoot Application with TestNG
Chapter 2 Integration Testing of Springboot with Cucumber and TestNG

SpringBoot with Gradle

Chapter 1 Testing of Gradle SpringBoot Application with Serenity, Cucumber and JUnit4
Chapter 2 Testing of Gradle SpringBoot Application with Serenity and JUnit5

CI/CD

Chapter 1 How to run SpringBoot tests with GitHub Actions
Chapter 2 How to run SpringBoot project in GitLab CI/CD

How to run Serenity BDD tests in Edge Browser

HOME

Serenity BDD has strong WebDriver integration and manages WebDriver instances. It is not needed to create or close the WebDriver instance of the Serenity Tests.

Serenity uses a library WebDriver Manager, which manages the driver for us. We don’t need to explicitly download and configure the WebDriver binaries for us.

webdriver {
  capabilities {
    browserName = "MicrosoftEdge"
    "ms:edgeOptions" {
      args = ["test-type", "ignore-certificate-errors", "headless",
        "incognito", "disable-infobars", "disable-gpu", "disable-default-apps", "disable-popup-blocking"]
    }
  }
}

edge {
    webdriver {
      capabilities {
        browserName = "MicrosoftEdge"
        "ms:edgeOptions" {
          args = ["start-maximized", "test-type", "ignore-certificate-errors",
            "incognito", "disable-infobars", "disable-gpu", "disable-default-apps", "disable-popup-blocking"]
        }
      }
    }
  }

@Managed annotation in Serenity will manage the WebDriver instance, including opening the appropriate driver at the start of each test, and shutting it down when the test is finished. @Managed provides an option for the user to select the WebDriver driver to the run the tests in it. The possible values are firefox, chrome, iexplorer, phantomjs, appium, safari, edge, and htmlunit. There are multiple ways to manage the WebDriver. One of the way is shown below:

In the below program, the tests are running on the Edge browser. The driver name is mentioned with @Managed annotation.

import net.serenitybdd.annotations.Managed;
import net.serenitybdd.annotations.Steps;
import net.serenitybdd.annotations.Title;
import net.serenitybdd.core.Serenity;
import net.serenitybdd.junit.runners.SerenityRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openqa.selenium.WebDriver;

import static org.assertj.core.api.Assertions.assertThat;

@RunWith(SerenityRunner.class)
public class EdgeTests {

    private String userName;
    private String passWord;
    private String errorMessage;

    @Managed(driver = "edge")
    WebDriver driver;

    @Steps
    NavigateActions navigate;

    @Steps
    StepLoginPage loginPage;


    @Test
    @Title("Login to application with invalid credential generates error message")
    public void invalidCredentials() {

        // Given
        navigate.toTheHomePage();

        // When
        loginPage.inputUserName("Admin");
        loginPage.inputPassword("admin");
        loginPage.clickLogin();

        // Then
        Serenity.reportThat("Passing invalid credentials generates error message",
                () -> assertThat(assertThat(loginPage.errorMessage()).isEqualToIgnoringCase("Invalid Credentials")));

    }

}

NavigateActions

import net.serenitybdd.annotations.Step;
import net.serenitybdd.core.steps.UIInteractionSteps;

public class NavigateActions extends UIInteractionSteps {

    @Step
    public void toTheHomePage() {
        openPageNamed("loginForm");
    }
}

import net.serenitybdd.annotations.Step;
import net.serenitybdd.core.pages.PageObject;
import net.serenitybdd.core.pages.WebElementFacade;
import org.openqa.selenium.support.FindBy;

public class StepLoginPage extends PageObject {

    @FindBy(name = "username")
    WebElementFacade username;

    @FindBy(name = "password")
    WebElementFacade password;

    @FindBy(xpath = "//*[@id='app']/div[1]/div/div[1]/div/div[2]/div[2]/form/div[3]/button")
    WebElementFacade submitButton;

    @FindBy(xpath = "//*[@id='app']/div[1]/div/div[1]/div/div[2]/div[2]/div/div[1]/div[1]/p")
    WebElementFacade errorMessage;

    @FindBy(xpath = "//*[@id='app']/div[1]/div/div[1]/div/div[2]/div[2]/form/div[4]/p")
    WebElementFacade linkText;

    @Step("Enter Username")
    public void inputUserName(String userName) {
        username.sendKeys((userName));
    }

    @Step("Enter Password")
    public void inputPassword(String passWord) {
        password.sendKeys((passWord));
    }

    @Step("Click Submit Button")
    public void clickLogin() {
        submitButton.click();
    }

    @Step("Error Message on unsuccessful login")
    public String errorMessage() {
        String actualErrorMessage = errorMessage.getText();
        return actualErrorMessage;
    }

    @Step("Click Forget Password Link")
    public void clickForgetPasswordLink() {
        linkText.click();

        System.out.println("Clicked on Forgot Password Link");
    }

}

Congratulations!! We are able to run the Serenity tests using edge browser.

Gradle Tutorials

Last Updated On

HOME

Gradle is an open-source build automation tool that is designed to be flexible enough to build almost any type of software.
Gradle runs on the JVM and you must have a Java Development Kit (JDK) installed to use it.
Several major IDEs allow you to import Gradle builds and interact with them: Android Studio, IntelliJ IDEA, Eclipse, and NetBeans.

Installation of Gradle

Chapter 1 How to install Gradle on Windows

Creation of Gradle project

Chapter 1 How to create Java Gradle project in Eclipse
Chapter 2 How to create a Java Gradle project using Command Line
Chapter 3 How to create Gradle project in IntelliJ
Chapter 4 How to create Gradle Java project in IntelliJ using Command Line

Importing of Gradle Project

Chapter 1 How to import Java Gradle project in Eclipse
Chapter 2 How to import Java Gradle project in IntelliJ

Gradle Project in Cucumber

Chapter 1 How To Create Gradle Project with Cucumber to test Rest API
Chapter 2 Run Gradle Cucumber Tests from Command Line
Chapter 3 Gradle Project with Cucumber, Selenium and TestNG
Chapter 4 Gradle Project with Cucumber, Selenium and JUnit4

Gradle Project in Serenity

Chapter 1 Serenity BDD with Gradle and Cucumber for Web Application
Chapter 2 Serenity BDD with Cucumber and Rest Assured in Gradle
Chapter 3 Serenity Emailable Report in Gradle

Gradle Project with Selenium

Chapter 1 How to create Gradle project with Selenium and TestNG
Chapter 2 How to create Gradle project with Selenium and JUnit4
Chapter 3 Gradle – Integration of Selenium and JUnit5

Gradle Project in Rest API

Chapter 1 Setup Basic REST Assured Gradle Project In Eclipse IDE

Allure Reports for Gradle Project

Chapter 1 Gradle – Allure Report for Selenium and TestNG
Chapter 2 Gradle – Allure Report for Selenium and JUnit4
Chapter 3 Gradle – Allure Report for Cucumber, Selenium and TestNG

Extent Reports for Gradle Project

Chapter 1 Gradle – Extent Report Version 5 for Cucumber, Selenium, and TestNG

Gradle with Jenkins

Chapter 1 Integrate Gradle project with Jenkins
Chapter 2 How to create Jenkins pipeline for Gradle project

Data Driven Tests using CSV file in Serenity

HOME

In the previous tutorial, I have explained the Data Driven Tests in Serenity where test data are defined in Tests. In this tutorial, I will explain the Data Driven tests in Serenity where we will get the test data from CSV file.

To start with this tutorial, refer this tutorial also which explains how to setup a project with Serenity and JUnit4.

Project Structure

Serenity lets us perform data-driven testing using test data in a CSV file. We store our test data in a CSV file (by default with columns separated by commas), with the first column acting as a header.

We need to create a test class containing properties that match the columns in the test data, as you did for the data-driven test in the previous example. The test class will typically contain one or more tests that use these properties as parameters to the test step or Page Object methods.

Here, we need to keep in mind that as the tests are parameterized , we need to use the Parameterized test runner to perform data-driven tests.

@RunWith(SerenityParameterizedRunner.class)

This is imported from below package

net.serenitybdd.junit.runners.SerenityParameterizedRunner;

@UseTestDataFrom annotation is used to indicate where to find the CSV file (this can either be a file on the classpath or a relative or absolute file path – putting the data set on the class path (e.g. in src/test/resources) makes the tests more portable).

@UseTestDataFrom(value = "testdata/credentials.csv")

Below is the example of the Parameterized Tests.

ParameterizedTestsUsingCSV Class contains the SerenityParameterizedRunner as well as provides the path of the test data file using @UseTestDataFrom, and the Tests.

The Serenity Parameterized Runner creates a new instance of this class for each row of data in the CSV file, assigning the properties with corresponding values in the test data. As you can see, I have mentioned 3 variables in the CSV file – userName, passWord, and errorMessage. I have declared the same private variables in the Test Class too – username, password, and errorMessage that match the columns in the test data file. Keep this in mind, that the column name should be the same in test data file and Test.

import net.serenitybdd.annotations.Managed;
import net.serenitybdd.annotations.Steps;
import net.serenitybdd.annotations.Title;
import net.serenitybdd.core.Serenity;
import net.serenitybdd.junit.runners.SerenityParameterizedRunner;
import net.thucydides.junit.annotations.Qualifier;
import net.thucydides.junit.annotations.TestData;
import net.thucydides.junit.annotations.UseTestDataFrom;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openqa.selenium.WebDriver;

import static org.assertj.core.api.Assertions.assertThat;

@RunWith(SerenityParameterizedRunner.class)
@UseTestDataFrom(value = "testdata/credentials.csv")
public class ParameterizedTests {

    private String userName;
    private String passWord;
    private String errorMessage;

    @Managed(options = "--start-maximized")
     WebDriver driver;

    @Steps
    NavigateActions navigate;

    @Steps
    StepLoginPage loginPage;


    @TestData(columnNames = "Username, Password, ErrorMessage")

    @Qualifier
    public String qualifier(){return " - " + " Username = " + userName + " and " + " Password = " + passWord + " should display " + errorMessage;}

    @Test
    @Title("Login to application with invalid credential generates error message")
    public void unsuccessfulLogin() {

        // Given
        navigate.toTheHomePage();

        // When
        loginPage.inputUserName(userName);
        loginPage.inputPassword(passWord);
        loginPage.clickLogin();

        // Then
        Serenity.reportThat("Passing invalid credentials generates error message",
                () -> assertThat(assertThat(loginPage.errorMessage()).isEqualToIgnoringCase(errorMessage)));

    }

}

The heading of parameters present in the Serenity Report (Index.html) like Username, Password, and Error Message are generated by @TestData(columnNames).

The description of the Test Step in the Serenity Report is modified by using @Qualifier. It is used to mark a method as a qualifier in an instantiated data-driven test case.

The test class needs to have a WebDriver instance with a @Managed annotation for Serenity to manage it in the background. That is all that is required, we do not need to manage the driver anymore. Each test class will need this driver variable declaration.

The Test Class uses Step Class (StepLoginPage) and Action Class (NavigateActions) to perform the Tests. StepLoginPage contains test steps that represent the level of abstraction between the code that interacts with the application. NavigateAction page is used to open an environment-specific page defined in the serenity.config file under the pages section.

StepLoginPage

import net.serenitybdd.annotations.Step;
import net.serenitybdd.core.pages.PageObject;
import net.serenitybdd.core.pages.WebElementFacade;
import org.openqa.selenium.support.FindBy;

public class StepLoginPage extends PageObject {

    @FindBy(name = "username")
    WebElementFacade username;

    @FindBy(name = "password")
    WebElementFacade password;

    @FindBy(xpath = "//*[@id='app']/div[1]/div/div[1]/div/div[2]/div[2]/form/div[3]/button")
    WebElementFacade submitButton;

    @FindBy(xpath = "//*[@id='app']/div[1]/div/div[1]/div/div[2]/div[2]/div/div[1]/div[1]/p")
    WebElementFacade errorMessage;

    @FindBy(xpath = "//*[@id='app']/div[1]/div/div[1]/div/div[2]/div[2]/form/div[4]/p")
    WebElementFacade linkText;

    @Step("Enter Username")
    public void inputUserName(String userName) {
        username.sendKeys((userName));
    }

    @Step("Enter Password")
    public void inputPassword(String passWord) {
        password.sendKeys((passWord));
    }

    @Step("Click Submit Button")
    public void clickLogin() {
        submitButton.click();
    }

    @Step("Error Message on unsuccessful login")
    public String errorMessage() {
        String actualErrorMessage = errorMessage.getText();
        return actualErrorMessage;
    }

    @Step("Click Forget Password Link")
    public void clickForgetPasswordLink() {
        linkText.click();

        System.out.println("Clicked on Forgot Password Link");
    }

}

NavigateActions

import net.serenitybdd.annotations.Step;
import net.serenitybdd.core.steps.UIInteractionSteps;

public class NavigateActions extends UIInteractionSteps {

    @Step
    public void toTheHomePage() {
        openPageNamed("loginForm");
    }
}

Serenity.config

headless.mode = false

pages{
  loginForm = "https://opensource-demo.orangehrmlive.com/"
  }

environments {
  chrome {
    webdriver {
      driver = chrome
      autodownload = true
      capabilities {
        browserName = "chrome"
        acceptInsecureCerts = true
        "goog:chromeOptions" {
          args = ["--start-maximized", "ignore-certificate-errors",
            "incognito", "disable-infobars", "disable-gpu", "disable-default-apps", "disable-popup-blocking"]
        }
      }
    }
  }
}

This test can be executed by JUnit as well as from the command line

JUnit – Right-click on the Test, select Run As, and then select JUnit Test in Eclipse.

If you are using IntelliJ, then right-click and select Run “ParameterizedTests”

The Test execution status can be seen as shown below:

To run the tests using the command line, use the below command

mvn clean verify

This will execute the tests and will generate the Test Execution Report as shown below.

The reports are generated as shown in the below image.

Serenity generates very descriptive and beautiful reports – Index.html and Serenity Summary Report.

Index.html

This page provides the detail about the Test, its corresponding test data, the status of each test scenario with screenshots, and the execution time of each test.

This is the expanded view of all the test steps of a test with their screenshots. This also shows the execution time of each step in the test.

Serenity Summary Report

This report is a single-page, self-contained HTML summary report, containing an overview of the test results, and a configurable breakdown of the status of different areas of the application.

We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

Serenity Report for Web Application with Cucumber6 and Junit

Last Updated On

HOME

In the previous tutorial, I explained the Testing of Web Application using Serenity BDD with Cucumber5 and JUnit4. In this tutorial, I’ll explain how to generate a Serenity Report for a web application using Serenity BDD with Cucumber6 and JUnit4.

Serenity BDD produces great test reports that act as Living Documentation for the product.

Table of Contents

  1. Prerequisite
  2. Dependency List
  3. Implementation Steps
    1. Update the Properties section in Maven pom.xml
    2. Add Serenity, Serenity Cucumber, and JUnit dependencies to POM.xml
    3. Update the Build Section of pom.xml
    4. Create a Feature file
    5. Create the Step Definition class or Glue Code
    6. Create a Serenity-Cucumber Runner class
    7. Create serenity.conf file under src/test/resources
    8. Create serenity.properties file at the root of the project
    9. Run the tests through the command line which generates Serenity Report
  4. Serenity Report
    1. Requirement View
    2. Test Results
    3. Capability
    4. Feature

Prerequisite

  1. Java 11 installed
  2. Maven installed
  3. Eclipse or IntelliJ installed

Dependency List:

  1. Java 17
  2. Maven – 3.9.6
  3. Serenity – 4.0.30
  4. Serenity Cucumber – 4.0.30
  5. JUnit – 4.13.2
  6. Maven Surefire Plugin – 3.2.3
  7. Maven Failsafe Plugin – 3.2.3
  8. Maven Compiler Plugin – 3.12.1

Implementation Steps

Step 1 – Update the Properties section in Maven pom.xml

 <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <serenity.version>4.0.30</serenity.version>
    <junit.version>4.13.2</junit.version>
    <maven.compiler.plugin.version>3.12.1</maven.compiler.plugin.version>
    <maven.surefire.plugin.version>3.2.3</maven.surefire.plugin.version>
    <maven.failsafe.plugin.version>3.2.3</maven.failsafe.plugin.version>
    <maven.compiler.source.version>17</maven.compiler.source.version>
    <maven.compiler.target.version>17</maven.compiler.target.version>
    <tags></tags>
    <parallel.tests></parallel.tests>
    <webdriver.base.url></webdriver.base.url>
 </properties>

Step 2 – Add Serenity, Serenity Cucumber, and JUnit dependencies to POM.xml

<dependencies>
    <dependency>
      <groupId>net.serenity-bdd</groupId>
      <artifactId>serenity-core</artifactId>
      <version>${serenity.version}</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>net.serenity-bdd</groupId>
      <artifactId>serenity-junit</artifactId>
      <version>${serenity.version}</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>net.serenity-bdd</groupId>
      <artifactId>serenity-screenplay-webdriver</artifactId>
      <version>${serenity.version}</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>net.serenity-bdd</groupId>
      <artifactId>serenity-cucumber</artifactId>
      <version>${serenity.version}</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>${junit.version}</version>
      <scope>test</scope>
    </dependency>

  </dependencies>

Step 3 – Update the Build Section of pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example</groupId>
  <artifactId>SerenityCucumberJunit4Demo</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>SerenityCucumberJunit4Demo</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <serenity.version>4.0.30</serenity.version>
    <junit.version>4.13.2</junit.version>
    <maven.compiler.plugin.version>3.12.1</maven.compiler.plugin.version>
    <maven.surefire.plugin.version>3.2.3</maven.surefire.plugin.version>
    <maven.failsafe.plugin.version>3.2.3</maven.failsafe.plugin.version>
    <maven.compiler.source.version>17</maven.compiler.source.version>
    <maven.compiler.target.version>17</maven.compiler.target.version>
    <tags></tags>
    <parallel.tests></parallel.tests>
    <webdriver.base.url></webdriver.base.url>
  </properties>

  <dependencies>
    <dependency>
      <groupId>net.serenity-bdd</groupId>
      <artifactId>serenity-core</artifactId>
      <version>${serenity.version}</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>net.serenity-bdd</groupId>
      <artifactId>serenity-junit</artifactId>
      <version>${serenity.version}</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>net.serenity-bdd</groupId>
      <artifactId>serenity-screenplay-webdriver</artifactId>
      <version>${serenity.version}</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>net.serenity-bdd</groupId>
      <artifactId>serenity-cucumber</artifactId>
      <version>${serenity.version}</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>${junit.version}</version>
      <scope>test</scope>
    </dependency>

  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>${maven.surefire.plugin.version}</version>

        <configuration>
          <skip>false</skip>
        </configuration>
      </plugin>

      <plugin>
        <artifactId>maven-failsafe-plugin</artifactId>
        <version>${maven.failsafe.plugin.version}</version>
        <configuration>
          <includes>
            <include>**/Test*.java</include>
          </includes>
          <systemPropertyVariables>
            <webdriver.base.url>${webdriver.base.url}</webdriver.base.url>
          </systemPropertyVariables>
          <parallel>classes</parallel>
          <threadCount>${parallel.tests}</threadCount>
          <forkCount>${parallel.tests}</forkCount>
        </configuration>
        <executions>
          <execution>
            <goals>
              <goal>integration-test</goal>
              <goal>verify</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>${maven.compiler.plugin.version}</version>
        <configuration>
          <source>${maven.compiler.source.version}</source>
          <target>${maven.compiler.target.version}</target>
        </configuration>
      </plugin>

      <plugin>
        <groupId>net.serenity-bdd.maven.plugins</groupId>
        <artifactId>serenity-maven-plugin</artifactId>
        <version>${serenity.version}</version>
        <dependencies>
          <dependency>
            <groupId>net.serenity-bdd</groupId>
            <artifactId>serenity-single-page-report</artifactId>
            <version>${serenity.version}</version>
          </dependency>
        </dependencies>
        <configuration>
          <tags>${tags}</tags>
          <reports>single-page-html</reports>
        </configuration>
        <executions>
          <execution>
            <id>serenity-reports</id>
            <phase>post-integration-test</phase>
            <goals>
              <goal>aggregate</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

Step 4 – Create a Feature file

Feature file should be saved as an extension of .feature. Add the test scenarios in this feature file. I have added sample test scenarios. The test scenarios are written in Gherkins language. A feature file is created under src/test/resources.

Feature: Login to HRM  

   @ValidCredentials
   Scenario: Login with valid credentials
   
    Given User is on Home page
    When User enters username as "Admin"
    And User enters password as "admin123"
    Then User should be able to login successfully
    
    @InValidCredentials    
    Scenario Outline: Login with invalid credentials
   
    Given User is on Home page
    When User enters username as '<username>'
    And User enters password as '<password>'
    Then User should be able to see error message '<errorMessage>'
      
   Examples:
    |username  |password  |errorMessage                    |
    |admin     |admin     |Invalid credentials             |
    |          |admin123  |Username cannot be empty        | 
    |Admin     |          |Password cannot be empty        |
    |          |          |Username cannot be empty        |
 
   @ForgetPassword  
   Scenario: Verify Forget Password Functionality
   
    Given User is on Home page
    When User clicks on Forgot your password link
    Then User should be able to see new page which contains Reset Password button
   

Step 5 – Create the Step Definition class or Glue Code

Create a StepDefinition class for LoginPage.feature.

package com.example.definitions;

import com.example.steps.StepDashboardPage;
import com.example.steps.StepForgetPasswordPage;
import com.example.steps.StepLoginPage;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import net.serenitybdd.annotations.Steps;
import org.junit.Assert;

import static org.junit.Assert.assertTrue;

public class LoginPageDefinitions {

    @Steps
    StepLoginPage loginPage;

    @Steps
    StepDashboardPage dashPage;

    @Steps
    StepForgetPasswordPage forgetpasswordPage;

    @Given("User is on Home page")
    public void openApplication() {
        loginPage.open();
        System.out.println("Page is opened");
    }

    @When("User enters username as {string}")
    public void enterUsername(String userName) {
        System.out.println("Enter Username");
        loginPage.inputUserName(userName);
    }

    @When("User enters password as {string}")
    public void enterPassword(String passWord) {
        loginPage.inputPassword(passWord);

        loginPage.clickLogin();
    }

    @Then("User should be able to login successfully")
    public void clickOnLoginButton() {
        dashPage.loginVerify();
    }

    @Then("User should be able to see error message {string}")
    public void unsuccessfulLogin(String expectedErrorMessage)  {

        String actualErrorMessage = loginPage.errorMessage();
        Assert.assertEquals(expectedErrorMessage, actualErrorMessage);
    }

    @When("User clicks on Forgot your password link")
    public void clickForgetPasswordLink() {
        loginPage.clickForgetPasswordLink();
    }

    @Then("User should be able to see new page which contains Reset Password button")
    public void verifyForgetPasswordPage() {

        assertTrue(forgetpasswordPage.ForgetPasswordPage());
    }

}

Serenity Step Libraries integrate smoothly into Cucumber Step Definition files; all you need to do is to annotate a step library variable with the @Steps annotation. Methods that represent a business task or action (inputUserName()), and that will appear in the reports as a separate step, is annotated with the @Step annotation. Other methods, such as loginVerify(), query the state of the application and are used in assert statements.

Here, I have created 3 StepClasses – StepLoginPage, StepDashboardPage, and StepForgetPasswordPage

StepLoginPage

package com.example.steps;

import net.serenitybdd.annotations.Step;
import net.serenitybdd.core.pages.PageObject;
import net.serenitybdd.core.pages.WebElementFacade;
import org.openqa.selenium.support.FindBy;

public class StepLoginPage extends PageObject {

    @FindBy(name = "username")
    WebElementFacade username;

    @FindBy(name = "password")
    WebElementFacade password;

    @FindBy(xpath = "//*[@id='app']/div[1]/div/div[1]/div/div[2]/div[2]/form/div[3]/button")
    WebElementFacade submitButton;

    @FindBy(xpath = "//*[@id='app']/div[1]/div/div[1]/div/div[2]/div[2]/div/div[1]/div[1]/p")
    WebElementFacade errorMessage;

    @FindBy(xpath = "//*[@id='app']/div[1]/div/div[1]/div/div[2]/div[2]/form/div[4]/p")
    WebElementFacade linkText;

    @Step("Enter Username")
    public void inputUserName(String userName) {
        username.sendKeys((userName));
    }

    @Step("Enter Password")
    public void inputPassword(String passWord) {
        password.sendKeys((passWord));
    }

    @Step("Click Submit Button")
    public void clickLogin() {
        submitButton.click();
    }

    @Step("Error Message on unsuccessful login")
    public String errorMessage() {
        String actualErrorMessage = errorMessage.getText();
        return actualErrorMessage;
    }

    @Step("Click Forget Password Link")
    public void clickForgetPasswordLink() {
        linkText.click();

        System.out.println("Clicked on Forgot Password Link");
    }

}

StepDashboardPage

package com.example.steps;

import net.serenitybdd.core.pages.PageObject;
import net.serenitybdd.core.pages.WebElementFacade;
import org.junit.Assert;
import org.openqa.selenium.support.FindBy;

public class StepDashboardPage extends PageObject {

    @FindBy(xpath = "//*[@id='app']/div[1]/div[1]/header/div[1]/div[1]/span/h6")
    WebElementFacade dashboardText;

    public void loginVerify() {

        String dashboardTitle = dashboardText.getText();
        Assert.assertTrue(dashboardTitle.contains("Dashboard"));
    }
}

StepForgetPasswordPage

package com.example.steps;

import net.serenitybdd.annotations.Step;
import net.serenitybdd.core.pages.PageObject;
import net.serenitybdd.core.pages.WebElementFacade;
import org.openqa.selenium.support.FindBy;

public class StepForgetPasswordPage extends PageObject {

    @FindBy(xpath = "//*[@id='app']/div[1]/div[1]/div/form/h6")
    WebElementFacade forgetLink;

    @Step("Verify Forget Password Page ")
    public boolean ForgetPasswordPage() {
        Boolean resetPasswordButton = forgetLink.isDisplayed();

        return resetPasswordButton;
    }
}

Step 6 – Create a Serenity-Cucumber Runner class

We cannot run a Feature file on its own in a cucumber-based framework. We need to create a Java class, which will run the Feature File. It is the starting point for JUnit to start executing the tests. TestRunner class creates under src/ test/java. When you run the tests with serenity, you use the CucumberWithSerenity test runner. If the feature files are not in the same package as the test runner class, you also need to use the @CucumberOptions class to provide the root directory where the feature files are found.

import org.junit.runner.RunWith;

import io.cucumber.junit.CucumberOptions;
import net.serenitybdd.cucumber.CucumberWithSerenity;

@RunWith(CucumberWithSerenity.class)
@CucumberOptions(plugin = {}, features = "src/test/resources/features/LoginPage.feature", glue = "com.example.definitions")

public class SerenityRunnerTests {

}

Step 7 – Create serenity.conf file under src/test/resources

Serenity.conf file is used to specify various features like the type of webdriver used, various test environments, run tests in headless mode, and many more options.

webdriver.driver. – This tells Serenity which browser to use for the test execution. You can configure this in several locations – serenity.properties or serenity.conf. Here, I have provided this information in serenity.conf

We can also configure the webdriver.base.url property for different environments in the serenity.conf configuration file, in the src/test/resources directory. Below is an example of the same.

headless.mode = false

environments {
  chrome {
    webdriver {
      driver = chrome
      autodownload = true
      capabilities {
        browserName = "chrome"
        acceptInsecureCerts = true
        "goog:chromeOptions" {
          args = ["test-type", "ignore-certificate-errors", "--window-size=1920,1080",
            "incognito", "disable-infobars", "disable-gpu", "disable-default-apps", "disable-popup-blocking"]
        }
      }
    }
  }
  edge {
    webdriver {
      capabilities {
        browserName = "MicrosoftEdge"
        "ms:edgeOptions" {
          args = ["test-type", "ignore-certificate-errors","--window-size=1920,1080",
            "incognito", "disable-infobars", "disable-gpu", "disable-default-apps", "disable-popup-blocking"]
        }
      }
    }
  }
  firefox {
    webdriver {
      capabilities {
        browserName = "firefox"
        pageLoadStrategy = "normal"
        acceptInsecureCerts = true
        unhandledPromptBehavior = "dismiss"
        strictFileInteractability = true

        "moz:firefoxOptions" {
          args = ["--window-size=1920,1080"],
          prefs {
            "javascript.options.showInConsole": false
          },
          log {"level": "info"},
        }
      }
    }
  }
}

#
# Define drivers for different platforms. Serenity will automatically pick the correct driver for the current platform
#

environments {
  default {
    webdriver.base.url = "https://opensource-demo.orangehrmlive.com/"
  }
  dev {
    webdriver.base.url = "https://opensource-demo.orangehrmlive.com/dev"
  }
  staging {
    webdriver.base.url = "https://opensource-demo.orangehrmlive.com/staging"
  }
  prod {
    webdriver.base.url = "https://opensource-demo.orangehrmlive.com/prod"
  }
}

Once the environment section is present in your serenity.conf file, you can use the environment system property to use the properties for a given environment. For example, the following would cause the staging URLs to be used:

mvn clean verify -Denvironment=staging

The default environment will be used if no other value is provided. In our example, I will not provide any environment, so it will pick the default environment.

Step 8 – Create serenity.properties file at the root of the project

serenity.project.name = Serenity and Cucumber Report Demo

Step 9 – Run the tests through the command line which generates Serenity Report

Open the command line and go to the location where pom.xml of the project is present and type the below command.

mvn clean verify -Denvironment=firefox

I have provided the location of the Firefox driver through the command line. I believe this is the best way to run the test. We can hard-code the path in the test code or in serenity.conf file. If you don’t want to pass the location of webdriver through the command line, then mention the details of webdriver in serenity.conf and just use the below command for execution.

mvn clean verify

Below is the image of the execution status.

This also provides the location of the serenity report as highlighted in the above image.

Serenity Report

Requirement View

In Serenity, requirements are organized in a hierarchy. We can get an idea of the full directory structure (in src/test/features directory) for the project.

The Test Results tab (shown below) tells you about the acceptance tests that were executed for this set of requirements. 

Test Results

At the bottom of the Test Results tab, you will find the actual test results – the list of all the tests, automated and manual, that were executed for this requirement.

Feature

This provides the detail of all the Test Scenarios present in a Feature File.

Below is an example of a Scenario Outline in the Report. It shows all the examples mentioned in the feature file.

This screen shows the test steps and screenshots of each step.

We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

The complete code can be found on GitHub – vibssingh/SerenityCucumberJUnit4_Demo.

Serenity BDD with Cucumber and JUnit4 for Web Application

HOME

Relationship between Web Application, Serenity BDD, Cucumber, and Selenium

Implementation Steps

Step 1: Add Serenity, Cucumber, and JUnit4 dependencies to the Maven project

The pom.xml will look like something as shown below.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example</groupId>
  <artifactId>SerenityCucumberJunit4Demo</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>SerenityCucumberJunit4Demo</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <serenity.version>4.0.30</serenity.version>
    <serenity.maven.version>3.5.1</serenity.maven.version>
    <junit.version>4.13.2</junit.version>
    <maven.compiler.plugin.version>3.12.1</maven.compiler.plugin.version>
    <maven.surefire.plugin.version>3.2.3</maven.surefire.plugin.version>
    <maven.failsafe.plugin.version>3.2.3</maven.failsafe.plugin.version>
    <maven.compiler.source.version>17</maven.compiler.source.version>
    <maven.compiler.target.version>17</maven.compiler.target.version>
    <tags></tags>
    <parallel.tests></parallel.tests>
    <webdriver.base.url></webdriver.base.url>
  </properties>

  <dependencies>
    <dependency>
      <groupId>net.serenity-bdd</groupId>
      <artifactId>serenity-core</artifactId>
      <version>${serenity.version}</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>net.serenity-bdd</groupId>
      <artifactId>serenity-junit</artifactId>
      <version>${serenity.version}</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>net.serenity-bdd</groupId>
      <artifactId>serenity-screenplay-webdriver</artifactId>
      <version>${serenity.version}</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>net.serenity-bdd</groupId>
      <artifactId>serenity-cucumber</artifactId>
      <version>${serenity.version}</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>${junit.version}</version>
      <scope>test</scope>
    </dependency>

  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>${maven.surefire.plugin.version}</version>

        <configuration>
          <skip>false</skip>
        </configuration>
      </plugin>

      <plugin>
        <artifactId>maven-failsafe-plugin</artifactId>
        <version>${maven.failsafe.plugin.version}</version>
        <configuration>
          <includes>
            <include>**/Test*.java</include>
          </includes>
          <systemPropertyVariables>
            <webdriver.base.url>${webdriver.base.url}</webdriver.base.url>
          </systemPropertyVariables>
          <parallel>classes</parallel>
          <threadCount>${parallel.tests}</threadCount>
          <forkCount>${parallel.tests}</forkCount>
        </configuration>
        <executions>
          <execution>
            <goals>
              <goal>integration-test</goal>
              <goal>verify</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>${maven.compiler.plugin.version}</version>
        <configuration>
          <source>${maven.compiler.source.version}</source>
          <target>${maven.compiler.target.version}</target>
        </configuration>
      </plugin>

      <plugin>
        <groupId>net.serenity-bdd.maven.plugins</groupId>
        <artifactId>serenity-maven-plugin</artifactId>
        <version>${serenity.version}</version>
        <dependencies>
          <dependency>
            <groupId>net.serenity-bdd</groupId>
            <artifactId>serenity-single-page-report</artifactId>
            <version>${serenity.version}</version>
          </dependency>
        </dependencies>
        <configuration>
          <tags>${tags}</tags>
          <reports>single-page-html</reports>
        </configuration>
        <executions>
          <execution>
            <id>serenity-reports</id>
            <phase>post-integration-test</phase>
            <goals>
              <goal>aggregate</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

Step 2: Create a Feature File under src/test/resources

Feature File is an entry point to the Cucumber tests. This is a file where you will describe your tests in Descriptive language (Like English). A feature file can contain a scenario or can contain many scenarios in a single feature file. Below is an example of a Feature file.

Feature: Login Page

@ValidCredentials
   Scenario: Login with valid credentials
   
    Given User is on Home page
    When User enters username as "Admin"
    And User enters password as "admin123"
    Then User should be able to login successfully
    
@InValidCredentials    
   Scenario Outline: Login with invalid credentials
   
    Given User is on Home page
    When User enters username as '<username>'
    And User enters password as '<password>'
    Then User should be able to see error message '<errorMessage>'
    
  Examples:
   | username   | password  | errorMessage                      |
   | $$$$$      | ££££££££  | Invalid credentials               |
   | admin      | Admin123  | Invalid credentials               | 
   | Admin123   | admin     | Invalid credentials               |  
    

Step 3: Create the Step Definition class

The glue code shown below uses Serenity step libraries as action classes to make the tests easier to read and to improve maintainability.

These classes declare using the Serenity @Steps annotation. The @Steps annotation 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 behavior: navigating to a particular page, performing a search, or retrieving the results of a search. These classes design to be small and self-contained, which makes them more stable and easier to maintain.

LoginPageDefinition contains the steps to open the web browser, enter the username, enter the password and click on the Login Button

package com.example.definitions;

import com.example.steps.StepDashboardPage;
import com.example.steps.StepLoginPage;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import net.serenitybdd.annotations.Steps;
import org.junit.Assert;

public class LoginPageDefinitions {

    @Steps
    StepLoginPage loginPage;

    @Steps
    StepDashboardPage dashPage;

    @Given("User is on Home page")
    public void openApplication() {
        loginPage.open();
        System.out.println("Page is opened");
    }

    @When("User enters username as {string}")
    public void enterUsername(String userName) {
        System.out.println("Enter Username");
        loginPage.inputUserName(userName);
    }

    @When("User enters password as {string}")
    public void enterPassword(String passWord) {
        loginPage.inputPassword(passWord);

        loginPage.clickLogin();
    }

    @Then("User should be able to login successfully")
    public void clickOnLoginButton() {
        dashPage.loginVerify();
    }

    @Then("User should be able to see error message {string}")
    public void unsucessfulLogin(String expectedErrorMessage) throws InterruptedException {

        String actualErrorMessage = loginPage.errorMessage();
        Assert.assertEquals(expectedErrorMessage, actualErrorMessage);
    }

}

This annotation lets you define a URL or a set of URLs that work with a particular page.

@DefaultUrl("https://opensource-demo.orangehrmlive.com/")

StepLoginPage is created by extending it from PageObject class. In this class,   $() method used below, which locates a web element using a By locator or an XPath or CSS expression. This class is responsible for uniquely locating elements on the page, and it does this by defining locators or occasionally by resolving web elements dynamically.

package com.example.steps;

import net.serenitybdd.annotations.Step;
import net.serenitybdd.core.pages.PageObject;
import net.serenitybdd.core.pages.WebElementFacade;
import org.openqa.selenium.support.FindBy;

public class StepLoginPage extends PageObject {

    @FindBy(name = "username")
    WebElementFacade username;

    @FindBy(name = "password")
    WebElementFacade password;

    @FindBy(xpath = "//*[@id='app']/div[1]/div/div[1]/div/div[2]/div[2]/form/div[3]/button")
    WebElementFacade submitButton;

    @FindBy(xpath = "//*[@id='app']/div[1]/div/div[1]/div/div[2]/div[2]/div/div[1]/div[1]/p")
    WebElementFacade errorMessage;

    @FindBy(xpath = "//*[@id='app']/div[1]/div/div[1]/div/div[2]/div[2]/form/div[4]/p")
    WebElementFacade linkText;

    @Step("Enter Username")
    public void inputUserName(String userName) {
        username.sendKeys((userName));
    }

    @Step("Enter Password")
    public void inputPassword(String passWord) {
        password.sendKeys((passWord));
    }

    @Step("Click Submit Button")
    public void clickLogin() {
        submitButton.click();
    }

    @Step("Error Message on unsuccessful login")
    public String errorMessage() {
        String actualErrorMessage = errorMessage.getText();
        return actualErrorMessage;
    }

}

StepDashboardPage is also created by extending Page Object Model. Here, we are verifying the Dashboard page

package com.example.steps;

import net.serenitybdd.core.pages.PageObject;
import net.serenitybdd.core.pages.WebElementFacade;
import org.junit.Assert;
import org.openqa.selenium.support.FindBy;

public class StepDashboardPage extends PageObject {

    @FindBy(xpath = "//*[@id='app']/div[1]/div[1]/header/div[1]/div[1]/span/h6")
    WebElementFacade dashboardText;

    public void loginVerify() {

        String dashboardTitle = dashboardText.getText();
        Assert.assertTrue(dashboardTitle.contains("Dashboard"));
    }
}

Step 4: Create Serenity Test Runner under src/test/java

We cannot run a Feature file on its own in a cucumber-based framework. We need to create a Java class, which will run the Feature File. It is the starting point for JUnit to start executing the tests. TestRunner class creates under src/test/java. When you run the tests with serenity, you use the CucumberWithSerenity test runner. If the feature files are not in the same package as the test runner class, you also need to use the @CucumberOptions class to provide the root directory where the feature files found.

import io.cucumber.junit.CucumberOptions;
import net.serenitybdd.cucumber.CucumberWithSerenity;
import org.junit.runner.RunWith;

@RunWith(CucumberWithSerenity.class)
@CucumberOptions(plugin = { "pretty" }, features = "src/test/resources/features/LoginPage.feature",
        glue="com.example.definitions")

public class SerenityRunnerTests {}

Step 5: Create serenity.conf (Configuration File)

Serenity uses serenity.conf file in the src/test/resources directory to configure test execution options. serenity.config can also contain the environment URL and other options like headless mode and soon. 

headless.mode = false

webdriver {
  driver = chrome
  capabilities {
    browserName = "chrome"
    acceptInsecureCerts = true
    "goog:chromeOptions" {
      args = ["remote-allow-origins=*","test-type", "no-sandbox", "ignore-certificate-errors", "--window-size=1920,1080",
        "incognito", "disable-infobars", "disable-gpu", "disable-default-apps", "disable-popup-blocking",
        "disable-dev-shm-usage", "disable-extensions", "disable-web-security", "disable-translate", "disable-logging"]
    }
  }
}


#
# Define drivers for different platforms. Serenity will automatically pick the correct driver for the current platform
#

environments {
  default {
    webdriver.base.url = "https://opensource-demo.orangehrmlive.com/"
  }
  dev {
    webdriver.base.url = "https://opensource-demo.orangehrmlive.com/dev"
  }
  staging {
    webdriver.base.url = "https://opensource-demo.orangehrmlive.com/staging"
  }
  prod {
    webdriver.base.url = "https://opensource-demo.orangehrmlive.com/prod"
  }
}

serenity.project.name = Serenity and Cucumber and JUnit4 Demo

Step 7: Executing the tests as JUnit Tests

We can run the tests as JUnit tests. Right-click on the Runner class and select Run As Junit Test (Eclipse).

Step 8: Executing the tests through the command line

You can run the tests from the command line by using the below command:

mvn clean verify

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

$ mvn clean verify -Ddriver=chrome

The test execution status looks like something this

Step 9: View the Serenity Reports

The test report generated by Serenity is placed under target/site/serenity.

There are a lot of reports under the Serenity folder. But we are interested in 2 reports – index.html and serenity-summary.html.

Index.html

Serenity-Summary.html

Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!! Cheers!!

Additional Tutorials:

Serenity BDD with Cucumber for SpringBoot Application
Serenity BDD with Cucumber and Rest Assured
Serenity Report for Web Application with Cucumber6 and Junit
Serenity Emailable HTML Report
Serenity BDD with Gradle and Cucumber for Web Application

Integration of Serenity with Cucumber and JUnit5

HOME

In the previous tutorial, I explained the Serenity BDD with Cucumber for Web Application using Junit4. In this tutorial, I will explain the same Test Framework using Serenity, Cucumber, and JUnit5. This tutorial gives a clear picture of the initial setup of a BDD Framework.

What is JUnit5?

JUnit 5 is composed of several different modules from three different sub-projects.

JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage

The JUnit Platform serves as a foundation for launching testing frameworks on the JVM. It also defines the TestEngine API for developing a testing framework that runs on the platform.

JUnit Jupiter is the combination of the new programming model and extension model for writing tests and extensions in JUnit 5. The Jupiter sub-project provides a TestEngine for running Jupiter based tests on the platform.

JUnit Vintage provides a TestEngine for running JUnit 3 and JUnit 4 based tests on the platform. It requires JUnit 4.12 or later to be present on the class/module path.

JUnit5 is not completely integrated with Serenity with Cucumber. So, it is advisable to use jupiter-vintage-engine for the Cucumber TestRunner classes.

Dependency List:

  1. Serenity – 4.0.28
  2. JUnit Jupiter – 5.10.1
  3. JUnit Vintage – 5.10.1
  4. JUnit Platform Suite – 1.10.1
  5. Cucumber JUnit Platform – 7.15.0
  6. Java 17
  7. Maven – 3.9.5
  8. Maven Compiler Plugin – 3.11.0
  9. Maven Surefire Plugin – 3.2.1
  10. Maven FailSafe Plugin – 3.2.1

Implementation Steps

Step 1- Download and Install Java

Click here to know How to install Java.

Step 2 – Download and setup Eclipse IDE on the system

The Eclipse IDE (integrated development environment) provides strong support for Java developers which is needed to write Java code. Click here to know How to install Eclipse.

Step 3 – Setup Maven and create a new Maven Project

Click here to know How to install Maven.

Click here to know How to create a Maven project

Below is the Maven project structure. Here,

Group Id – com.example
Artifact Id – SerenityCucumberJunit5Demo
Version – 0.0.1-SNAPSHOT
Package – com. example. SerenityCucumberJunit5Demo

Step 4 – Update Properties section in Maven pom.xml

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <serenity.version>4.0.28</serenity.version>
        <junit.jupiter.version>5.10.1</junit.jupiter.version>
        <junit.vintage.version>5.10.1</junit.vintage.version>
        <junit-platform-suite.version>1.10.1</junit-platform-suite.version>
        <cucumber-junit-platform-engine.version>7.15.0</cucumber-junit-platform-engine.version>
        <maven.compiler.plugin.version>3.11.0</maven.compiler.plugin.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <maven.surefire.plugin.version>3.2.1</maven.surefire.plugin.version>
        <maven.failsafe.plugin.version>3.2.1</maven.failsafe.plugin.version>
        <tags></tags>
  </properties>

Step 5 – Add repositories and pluginRepository to Maven pom.xml

 <repositories>
        <repository>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
            <id>central</id>
            <name>bintray</name>
            <url>https://jcenter.bintray.com</url>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
            <id>central</id>
            <name>bintray-plugins</name>
            <url>https://jcenter.bintray.com</url>
        </pluginRepository>
    </pluginRepositories>

Step 6 – Add Serenity, Serenity Cucumber, and JUnit dependencies to POM.xml

<dependencies>
        <!-- JUnit 5 -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>${junit.jupiter.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.junit.vintage</groupId>
            <artifactId>junit-vintage-engine</artifactId>
            <version>${junit.vintage.version}</version>
            <scope>test</scope>
        </dependency>

        <!-- Serenity -->
         <dependency>
            <groupId>net.serenity-bdd</groupId>
            <artifactId>serenity-core</artifactId>
            <version>${serenity.version}</version>
            <scope>test</scope>
        </dependency>
        
         <dependency>
            <groupId>net.serenity-bdd</groupId>
            <artifactId>serenity-cucumber</artifactId>
            <version>${serenity.version}</version>
            <scope>test</scope>
        </dependency>
        
        <dependency>
            <groupId>net.serenity-bdd</groupId>
            <artifactId>serenity-screenplay-webdriver</artifactId>
            <version>${serenity.version}</version>
            <scope>test</scope>
        </dependency>

     <dependency>
         <groupId>org.junit.platform</groupId>
         <artifactId>junit-platform-suite</artifactId>
         <version>${junit-platform-suite.version}</version>
         <scope>test</scope>
     </dependency>

     <dependency>
         <groupId>io.cucumber</groupId>
         <artifactId>cucumber-junit-platform-engine</artifactId>
         <version>${cucumber-junit-platform-engine.version}</version>
         <scope>test</scope>
     </dependency>

    </dependencies>

Step 7 – Update the Build Section of pom.xml

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>${maven.surefire.plugin.version}</version>
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>${maven.failsafe.plugin.version}</version>
                <configuration>
                    <includes>
                        <include>**/*.java</include>
                    </includes>
                    <parallel>methods</parallel>
                    <useUnlimitedThreads>true</useUnlimitedThreads>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven.compiler.plugin.version}</version>
                <configuration>
                    <source>${maven.compiler.source}</source>
                    <target>${maven.compiler.target}</target>
                </configuration>
            </plugin>
           <plugin>
               <groupId>net.serenity-bdd.maven.plugins</groupId>
               <artifactId>serenity-maven-plugin</artifactId>
               <version>${serenity.version}</version>
               <dependencies> 
                  <dependency>
                       <groupId>net.serenity-bdd</groupId>
                       <artifactId>serenity-single-page-report</artifactId>
                       <version>${serenity.version}</version>
                  </dependency>                
               </dependencies>
               <configuration>
                   <tags>${tags}</tags>
                   <reports>single-page-html</reports> 
               </configuration>
               <executions>
                  <execution>
                      <id>serenity-reports</id>
                      <phase>post-integration-test</phase>
                      <goals>
                          <goal>aggregate</goal>
                      </goals>
                   </execution>
               </executions>
           </plugin>
        </plugins>
    </build>
</project>

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example</groupId>
  <artifactId>SerenityCucumberJunit5Demo</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <name>SerenityCucumberJunit5Demo</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <serenity.version>4.0.28</serenity.version>
        <junit.jupiter.version>5.10.1</junit.jupiter.version>
        <junit.vintage.version>5.10.1</junit.vintage.version>
        <junit-platform-suite.version>1.10.1</junit-platform-suite.version>
        <cucumber-junit-platform-engine.version>7.15.0</cucumber-junit-platform-engine.version>
        <maven.compiler.plugin.version>3.11.0</maven.compiler.plugin.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <maven.surefire.plugin.version>3.2.1</maven.surefire.plugin.version>
        <maven.failsafe.plugin.version>3.2.1</maven.failsafe.plugin.version>
        <tags></tags>
  </properties>
  
  <repositories>
        <repository>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
            <id>central</id>
            <name>bintray</name>
            <url>https://jcenter.bintray.com</url>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
            <id>central</id>
            <name>bintray-plugins</name>
            <url>https://jcenter.bintray.com</url>
        </pluginRepository>
    </pluginRepositories>

 <dependencies>
        <!-- JUnit 5 -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>${junit.jupiter.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.junit.vintage</groupId>
            <artifactId>junit-vintage-engine</artifactId>
            <version>${junit.vintage.version}</version>
            <scope>test</scope>
        </dependency>

        <!-- Serenity -->
         <dependency>
            <groupId>net.serenity-bdd</groupId>
            <artifactId>serenity-core</artifactId>
            <version>${serenity.version}</version>
            <scope>test</scope>
        </dependency>
        
         <dependency>
            <groupId>net.serenity-bdd</groupId>
            <artifactId>serenity-cucumber</artifactId>
            <version>${serenity.version}</version>
            <scope>test</scope>
        </dependency>
        
        <dependency>
            <groupId>net.serenity-bdd</groupId>
            <artifactId>serenity-screenplay-webdriver</artifactId>
            <version>${serenity.version}</version>
            <scope>test</scope>
        </dependency>

     <dependency>
         <groupId>org.junit.platform</groupId>
         <artifactId>junit-platform-suite</artifactId>
         <version>${junit-platform-suite.version}</version>
         <scope>test</scope>
     </dependency>

     <dependency>
         <groupId>io.cucumber</groupId>
         <artifactId>cucumber-junit-platform-engine</artifactId>
         <version>${cucumber-junit-platform-engine.version}</version>
         <scope>test</scope>
     </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>${maven.surefire.plugin.version}</version>
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>${maven.failsafe.plugin.version}</version>
                <configuration>
                    <includes>
                        <include>**/*.java</include>
                    </includes>
                    <parallel>methods</parallel>
                    <useUnlimitedThreads>true</useUnlimitedThreads>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven.compiler.plugin.version}</version>
                <configuration>
                    <source>${maven.compiler.source}</source>
                    <target>${maven.compiler.target}</target>
                </configuration>
            </plugin>
           <plugin>
               <groupId>net.serenity-bdd.maven.plugins</groupId>
               <artifactId>serenity-maven-plugin</artifactId>
               <version>${serenity.version}</version>
               <dependencies> 
                  <dependency>
                       <groupId>net.serenity-bdd</groupId>
                       <artifactId>serenity-single-page-report</artifactId>
                       <version>${serenity.version}</version>
                  </dependency>                
               </dependencies>
               <configuration>
                   <tags>${tags}</tags>
                   <reports>single-page-html</reports> 
               </configuration>
               <executions>
                  <execution>
                      <id>serenity-reports</id>
                      <phase>post-integration-test</phase>
                      <goals>
                          <goal>aggregate</goal>
                      </goals>
                   </execution>
               </executions>
           </plugin>
        </plugins>
    </build>
</project>

Step 8 – Create a feature file under src/test/resources

The purpose of the Feature keyword is to provide a high-level description of a software feature, and to group related scenarios. To know more about the Feature file, please refer this tutorial.

Feature: Login to HRM  

   @ValidCredentials
   Scenario: Login with valid credentials
   
    Given User is on Home page
    When User enters username as "Admin"
    And User enters password as "admin123"
    Then User should be able to login successfully
    
    @InValidCredentials    
    Scenario Outline: Login with invalid credentials
   
    Given User is on Home page
    When User enters username as '<username>'
    And User enters password as '<password>'
    Then User should be able to see error message '<errorMessage>'
      
   Examples:
    |username   |password       |errorMessage               |
    |admin        |admin            |Invalid credentials        |
    |abc            |admin123       |Invalid credentials        |
    |abc            |abc123           |Invalid credentials         |
    |1$£"          | 45£"%           |Invalid credentials        |
 
   @ForgetPassword  
   Scenario: Verify Forget Password Functionality
   
    Given User is on Home page
    When User clicks on Forgot your password link
    Then User should be able to see new page which contains Reset Password button

Step 9 – Create junit-platform.properties file under src/test/resources (optional)

This is an optional step. Cucumber of version 6.7 and above provides the functionality to generate a beautiful cucumber report. For this, it is needed to add a file junit-platform.properties under src/test/resources.

cucumber.publish.enabled = true

Step 10 – Create the Step Definition class or Glue Code

A Step Definition is a Java method with an expression that links it to one or more Gherkin steps. When Cucumber executes a Gherkin step in a scenario, it will look for a matching step definition to execute. You can have all of your step definitions in one file, or in multiple files.

LoginPageDefinitions

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import com.example.SerenityCucumberJunit5Demo.steps.StepDashboardPage;
import com.example.SerenityCucumberJunit5Demo.steps.StepForgetPasswordPage;
import com.example.SerenityCucumberJunit5Demo.steps.StepLoginPage;

import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import net.serenitybdd.annotations.Steps;


public class LoginPageDefinitions {

	@Steps
	StepLoginPage loginPage;

	@Steps
	StepDashboardPage dashPage;

	@Steps
	StepForgetPasswordPage forgetpasswordPage;

	@Given("User is on Home page")
	public void openApplication() {
		loginPage.open();
	}

	@When("User enters username as {string}")
	public void enterUsername(String userName) {

		loginPage.inputUserName(userName);
	}

	@When("User enters password as {string}")
	public void enterPassword(String passWord) {
		loginPage.inputPassword(passWord);
		loginPage.clickLogin();
	}

	@Then("User should be able to login successfully")
	public void clickOnLoginButton() {
		dashPage.loginVerify();
	}

	@Then("User should be able to see error message {string}")
	public void unsucessfulLogin(String expectedErrorMessage) {
		String actualErrorMessage = loginPage.errorMessage();

		System.out.println("Actual Error Message :" + actualErrorMessage);

		assertEquals(expectedErrorMessage, actualErrorMessage);
	}

	@When("User clicks on Forgot your password link")
	public void clickForgetPasswordLink() {
		loginPage.clickForgetPasswordLink();
	}

	@Then("User should be able to see new page which contains Reset Password button")
	public void verifyForgetPasswordPage() {

		assertTrue(forgetpasswordPage.ForgetPasswordPage());
	}
}

Assertions in JUnit-Vintage Engine are imported from the below package:-

import static org.junit.jupiter.api.Assertions.*;

DashboardPageDefinitions

import com.example.SerenityCucumberJunit5Demo.steps.StepDashboardPage;
import net.serenitybdd.annotations.Step;
import net.serenitybdd.annotations.Steps;

public class DashboardPageDefinitions {

	@Steps
	StepDashboardPage dashPage;

	@Step
	public void verifyAdminLogin() {
		dashPage.loginVerify();
	}
}

The corresponding Test Step classes are – StepLoginPage and StepDashboardPage.

There are multiple ways to identify a web element on the web page – one of the ways is to use @FindBy or $(By.).

I prefer to use @FindBy as I need not find the same element multiple times. Using @FindBy, I have identified a web element and defined a WebElementFacacde for the same which is reusable.

StepLoginPage

import net.serenitybdd.annotations.Step;
import net.serenitybdd.core.annotations.findby.FindBy;
import net.serenitybdd.core.pages.PageObject;
import net.serenitybdd.core.pages.WebElementFacade;


public class StepLoginPage extends PageObject {

	@FindBy(name = "username")
	WebElementFacade username;

	@FindBy(name = "password")
	WebElementFacade password;

	@FindBy(xpath = "//*[@id='app']/div[1]/div/div[1]/div/div[2]/div[2]/form/div[3]/button")
	WebElementFacade submitButton;

	@FindBy(xpath = "//*[@id='app']/div[1]/div/div[1]/div/div[2]/div[2]/div/div[1]/div[1]/p")
	WebElementFacade errorMessage;

	@FindBy(xpath = "//*[@id='app']/div[1]/div/div[1]/div/div[2]/div[2]/form/div[4]/p")
	WebElementFacade linkText;

	@Step("Enter Username")
	public void inputUserName(String userName) {
		username.sendKeys((userName));
	}

	@Step("Enter Password")
	public void inputPassword(String passWord) {
		password.sendKeys((passWord));
	}

	@Step("Click Submit Button")
	public void clickLogin() {
		submitButton.click();
	}

	@Step("Error Message on unsuccessful login")
	public String errorMessage() {
		String actualErrorMessage = errorMessage.getText();
		System.out.println("Actual Error Message :" + actualErrorMessage);

		return actualErrorMessage;
	}

	@Step("Click Forget Password Link")
	public void clickForgetPasswordLink() {
		linkText.click();

		System.out.println("Clicked on Forgot Password Link");
	}

}

StepDashboardPage

import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;
import net.serenitybdd.annotations.Step;
import net.serenitybdd.core.annotations.findby.FindBy;
import net.serenitybdd.core.pages.PageObject;
import net.serenitybdd.core.pages.WebElementFacade;

public class StepDashboardPage extends PageObject {

	@FindBy(xpath = "//*[@id='app']/div[1]/div[1]/header/div[1]/div[1]/span/h6")
	WebElementFacade dashboardText;

	@Step("Successful login")
	public void loginVerify() {
		String dashboardTitle = dashboardText.getText();
		assertThat(dashboardTitle, containsString("Dashboard"));
	}
}

StepForgetPasswordPage

import net.serenitybdd.annotations.Step;
import net.serenitybdd.core.annotations.findby.FindBy;
import net.serenitybdd.core.pages.PageObject;
import net.serenitybdd.core.pages.WebElementFacade;

public class StepForgetPasswordPage extends PageObject {

	@FindBy(xpath = "//*[@id='app']/div[1]/div[1]/div/form/h6")
	WebElementFacade forgetLink;

	@Step("Verify Forget Password Page ")
	public boolean ForgetPasswordPage() {
		Boolean resetPasswordButton = forgetLink.isDisplayed();

		return resetPasswordButton;
	}
}

Step 11 – Create a Serenity-Cucumber Runner class

Cucumber runs the feature files via JUnit and needs a dedicated test runner class to actually run the feature files. When you run the tests with Serenity, you use the CucumberWithSerenity test runner. You also need to use the @CucumberOptions class to provide the root directory where the feature files can be found.

import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME;
import static io.cucumber.junit.platform.engine.Constants.PLUGIN_PROPERTY_NAME;

import org.junit.platform.suite.api.ConfigurationParameter;
import org.junit.platform.suite.api.IncludeEngines;
import org.junit.platform.suite.api.SelectClasspathResource;
import org.junit.platform.suite.api.Suite;

@Suite
@IncludeEngines("cucumber")
@SelectClasspathResource("/features")
@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "com.example.SerenityCucumberJunit5Demo.definitions")
@ConfigurationParameter(key = PLUGIN_PROPERTY_NAME, value = "io.cucumber.core.plugin.SerenityReporterParallel,pretty,timeline:build/test-results/timeline")

public class SerenityRunnerTest {

}

Step 12 – Create serenity.conf file under src/test/resources

The serenity configuration file is used to configure the drivers so the test cases can run successfully. This file contains an operating system-specific binary. The binary file sits between your test and the browser. It acts as an intermediary, an interface between your tests and the browser you are using.

You can also configure the webdriver.base.url property for different environments in the serenity.conf configuration file.

headless.mode = false

webdriver {
  driver = chrome
  capabilities {
    browserName = "chrome"
    acceptInsecureCerts = true
    "goog:chromeOptions" {
      args = ["remote-allow-origins=*","test-type", "no-sandbox", "ignore-certificate-errors", "--window-size=1000,800",
        "incognito", "disable-infobars", "disable-gpu", "disable-default-apps", "disable-popup-blocking",
        "disable-dev-shm-usage", "disable-extensions", "disable-web-security", "disable-translate", "disable-logging"]
    }
  }
}



#
# Define drivers for different platforms. Serenity will automatically pick the correct driver for the current platform
#

environments {
  default {
    webdriver.base.url = "https://opensource-demo.orangehrmlive.com/"
  }
  dev {
    webdriver.base.url = "https://opensource-demo.orangehrmlive.com/dev"
  }
  staging {
    webdriver.base.url = "https://opensource-demo.orangehrmlive.com/staging"
  }
  prod {
    webdriver.base.url = "https://opensource-demo.orangehrmlive.com/prod"
  }
}

Step 13 – Create serenity.properties file at the root of the project

serenity.project.name = Serenity and Cucumber and JUnit5 Demo

Step 14 – Run the tests from Command Line

Open the command line and go to the location where pom.xml of the project is present and type the below command.

mvn clean verify

Step 15 – Test Execution Status

The image displayed above shows the execution status.

The feature file contains 3 test cases. Test Case 2 is a Test Scenario that has 4 examples. So, in total we have 6 tests. This information is clearly mentioned in the new version of Serenity.

Step 16 – Serenity Report Generation

The best part about Serenity is the report generation by it. The Reports contain all possible types of information, you can think of with minimal extra effort. There are multiple types of reports are generated. We are interested in index.html and serenity-summary.html. To know more about Serenity Reports, please refer to tutorials for Index.html and Serenity-Summary.html. Below is the new Serenity Report.

  1. index.html

2. serenity-summary.html

Step 17 – Cucumber Report Generation (Optional)

Every Test Execution generates a Cucumber Report (Version 6.7.0) and above as shown in the image.

Copy the URL and paste it to a browser and it shows the report as shown below:

To know more about Cucumber Reports, refer to this tutorial.

We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!