Integration of Allure Report with Rest Assured and JUnit4

HOME

In the previous tutorial, I explained the Allure Report with Cucumber, Selenium and JUnit4. In this tutorial, I will explain how to Integrate Allure Report with Rest Assured and JUnit4.

The below example covers the implementation of Allure Report for Rest API using Rest Assured, JUnit4, Java, and Maven.

Prerequisite

  1. Java 11 or above installed
  2. Maven installed
  3. Eclipse or IntelliJ installed
  4. Allure installed

Dependency List:

  1. Java 17
  2. Maven – 3.9.6
  3. Allure Maven – 2.12.0
  4. Rest Assured – 5.3.4
  5. Allure Rest Assured – 2.25.0
  6. Allure JUnit4 – 2.25.0
  7. Aspectj – 1.9.21
  8. JUnit – 4.13.2

Implementation Steps

Step 1 – Update Properties section in Maven pom.xml

<properties>
        <rest-assured.version>5.4.0</rest-assured.version>
        <junit.version>4.13.2</junit.version>
        <json.version>20231013</json.version>
        <hamcrest.version>1.3</hamcrest.version>
        <allure.maven.version>2.12.0</allure.maven.version>
        <allure.junit.version>2.25.0</allure.junit.version>
        <allure.rest.assured.version>2.25.0</allure.rest.assured.version>
        <maven.compiler.plugin.version>3.12.1</maven.compiler.plugin.version>
        <maven.surefire.plugin.version>3.2.3</maven.surefire.plugin.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <aspectj.version>1.9.21</aspectj.version>
</properties>

Step 2 – Add the Allure-Rest Assured dependency

<!--Allure Reporting Dependency-->   
<dependency>
    <groupId>io.qameta.allure</groupId>
    <artifactId>allure-rest-assured</artifactId>
    <version>${allure.rest-assured.version}</version>
</dependency>

Add other dependencies like Rest Assured and Allure-JUnit4 dependencies in POM.xml

<dependencies>

        <!-- Rest-Assured Dependency -->
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
            <version>${rest-assured.version}</version>
            <scope>test</scope>
        </dependency>

        <!-- JUnit4 Dependency -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>

        <!-- JSON Dependency -->
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>${json.version}</version>
        </dependency>

        <!-- Allure JUnit Dependency -->
        <dependency>
            <groupId>io.qameta.allure</groupId>
            <artifactId>allure-junit4</artifactId>
            <version>${allure.junit.version}</version>
        </dependency>

        <!-- Allure Rest-assured Dependency-->
        <dependency>
            <groupId>io.qameta.allure</groupId>
            <artifactId>allure-rest-assured</artifactId>
            <version>${allure.rest.assured.version}</version>
        </dependency>

    </dependencies>

Step 3 – Update the Build Section of pom.xml in Allure Report Project

<build>
        <plugins>

            <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>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>${maven.surefire.plugin.version}</version>
                <configuration>
                    <testFailureIgnore>true</testFailureIgnore>
                    <argLine>
                        -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
                    </argLine>
                    <properties>
                        <property>
                            <name>listener</name>
                            <value>io.qameta.allure.junit4.AllureJunit4</value>
                        </property>
                    </properties>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjweaver</artifactId>
                        <version>${aspectj.version}</version>
                    </dependency>
                </dependencies>
            </plugin>

            <plugin>
                <groupId>io.qameta.allure</groupId>
                <artifactId>allure-maven</artifactId>
                <version>${allure.maven.version}</version>
                <configuration>
                    <reportVersion>${allure.maven.version}</reportVersion>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Step 4 – Create a Test Code for the testing of REST API under src/test/java

Rest Assured and Allure Report are two popular tools for testing. Rest Assured is used for API testing and Allure Report is used for creating detailed reports about tests. To see our request and response in more detail using these tools, we need to add a line to our Rest Assured tests. This will provide the request and response details in the report.

.filter(new AllureRestAssured())

package org.example;

import io.qameta.allure.*;
import io.qameta.allure.restassured.AllureRestAssured;
import io.restassured.http.ContentType;
import org.json.JSONObject;
import org.junit.Test;

import static io.restassured.RestAssured.given;
import static org.hamcrest.core.IsEqual.equalTo;

@Epic("REST API Regression Testing using JUnit4")
@Feature("Verify CRUID Operations on Employee module")
public class APITests {

    String BaseURL = "https://dummy.restapiexample.com/api";


    @Test
    @Story("GET Request")
    @Severity(SeverityLevel.NORMAL)
    @Description("Test Description : Verify the details of employee of id-2")
    public void getUser() {

        // GIVEN
        given()
                .filter(new AllureRestAssured())

                // WHEN
                .when()
                .get(BaseURL + "/v1/employee/2")

                // THEN
                .then()
                .statusCode(200)
                .statusLine("HTTP/1.1 200 OK")
                // To verify booking id at index 2
                .body("data.employee_name", equalTo("Garrett Winters!"))
                .body("message", equalTo("Successfully! Record has been fetched."));

    }

    @Test
    @Story("POST Request")
    @Severity(SeverityLevel.NORMAL)
    @Description("Test Description : Verify the creation of a new employee")
    public void createUser() {

        JSONObject data = new JSONObject();

        data.put("employee_name", "APITest");
        data.put("employee_salary", "99999");
        data.put("employee_age", "30");

        // GIVEN
        given()
                .filter(new AllureRestAssured())
                .contentType(ContentType.JSON)
                .body(data.toString())

                // WHEN
                .when()
                .post(BaseURL + "/v1/create")

                // THEN
                .then()
                .statusCode(200)
                .body("data.employee_name", equalTo("APITest"))
                .body("message", equalTo("Successfully! Record has been added."));

    }
}

Step 5 – Run the Test and Generate Allure Report

To run the tests, use the below command

mvn clean test

The output of the above program is

This will create allure-results folder with all the test reports. These files will be used to generate Allure Report.

To create Allure Report, use the below command

allure serve

This will generate the beautiful Allure Test Report as shown below.

Allure Report Dashboard

Categories in Allure Report

The categories tab gives you a way to create custom defects classifications to apply for test results. There are two categories of defects – Product Defects (failed tests) and Test Defects (broken tests).

Suites in Allure Report

On the Suites tab a standard structural representation of executed tests, grouped by suites and classes can be found.

View test history

Each time you run the report from the command line with the mvn clean test command, a new result JSON file will get added to the allure-results folder. Allure can use those files to include a historical view of your tests. Let’s give that a try.

To get started, run mvn clean test a few times and watch how the number of files in the allure-reports folder grows.

Now go back to view your report. Select Suites from the left nav, select one of your tests and click Retries in the right pane. You should see the history of test runs for that test:

Graphs in Allure Report

Graphs allow you to see different statistics collected from the test data: status breakdown or severity and duration diagrams.

Timeline in Allure Report

Timeline tab visualizes retrospective of tests execution, allure adaptors collect precise timings of tests, and here on this tab, they are arranged accordingly to their sequential or parallel timing structure.

Behaviors of Allure Report

This tab groups test results according to Epic, Feature, and Story tags.

The below image shows the request body sent and the status code of the response, its body, and header provided by API.

Packages in Allure Report

The packages tab represents a tree-like layout of test results, grouped by different packages.

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

Allure Report with Cucumber, Selenium and TestNG

Last Updated On

HOME

In the previous tutorial, I explained the Integration of the Allure Report with Selenium and TestNG. In this tutorial, I will explain how to Integrate Allure Report with Cucumber, Selenium, and TestNG.

The below example covers the implementation of Allure Reports with Cucumber, Selenium, TestNG, Java, and Maven. Before starting, make sure to install Allure on your machine. Refer to this tutorial to install allure – What is Allure Report?.

Table of Contents

  1. Prerequisite
  2. Dependency List
  3. Implementation Steps
    1. Update the Properties section in Maven pom.xml
    2. Add Cucumber5, Selenium, TestNG, Allure-Cucumber5, and Allure-TestNG dependencies
    3. Update the Build Section of pom.xml in the Allure Report Project
    4. Create a Feature file
    5. Create the Step Definition class or Glue Code
    6. Create a TestNG Cucumber Runner class
    7. Create testng.xml for the project
    8. Run the Test and Generate Allure Report
  4. Allure Report Dashboard
    1. Categories in Allure Report
    2. Suites in Allure Report
    3. Graphs in Allure Report
    4. Timeline in Allure Report
    5. Behaviours of Allure Report
    6. Packages in Allure Report

Prerequisite

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

Dependency List

  1. Selenium – 4.16.1
  2. Java 17
  3. Cucumber – 7.15.0
  4. Maven – 3.9.6
  5. Allure Report – 2.25.0
  6. Allure Maven – 2.12.0
  7. Aspectj – 1.9.21
  8. Maven Compiler Plugin – 3.12.1
  9. Maven Surefire Plugin – 3.2.3

Implementation Steps

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

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <cucumber.version>7.15.0</cucumber.version>
    <selenium.version>4.16.1</selenium.version>
    <testng.version>7.9.0</testng.version>
    <maven.compiler.plugin.version>3.12.1</maven.compiler.plugin.version>
    <maven.surefire.plugin.version>3.2.3</maven.surefire.plugin.version>
    <maven.compiler.source.version>17</maven.compiler.source.version>
    <maven.compiler.target.version>17</maven.compiler.target.version>
    <allure.junit4.version>2.25.0</allure.junit4.version>
    <aspectj.version>1.9.21</aspectj.version>
    <allure.version>2.25.0</allure.version>
    <allure.maven>2.12.0</allure.maven>
</properties>

Step 2 – Add dependencies to pom.xml

Add Cucumber, Selenium, TestNG, Allure-Cucumber, and Allure-TestNG dependencies to pom.xml (Maven Project).

<dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>io.qameta.allure</groupId>
        <artifactId>allure-bom</artifactId>
        <version>${allure.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>


  <dependencies>

    <dependency>
      <groupId>io.cucumber</groupId>
      <artifactId>cucumber-java</artifactId>
      <version>${cucumber.version}</version>
    </dependency>

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

    <!-- Selenium -->
    <dependency>
      <groupId>org.seleniumhq.selenium</groupId>
      <artifactId>selenium-java</artifactId>
      <version>${selenium.version}</version>
    </dependency>

    <!-- TestNG -->
    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>${testng.version}</version>
      <scope>test</scope>
    </dependency>

    <!--Allure Cucumber Dependency-->
    <dependency>
      <groupId>io.qameta.allure</groupId>
      <artifactId>allure-cucumber7-jvm</artifactId>
      <scope>test</scope>
    </dependency>

    <!--Allure Reporting Dependency-->
    <dependency>
      <groupId>io.qameta.allure</groupId>
      <artifactId>allure-testng</artifactId>
      <scope>test</scope>
    </dependency>

  </dependencies>

Step 3 – Update the Build Section of pom.xml in the Allure Report Project

<build>
    <plugins>
      <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>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>${maven.surefire.plugin.version}</version>
        <configuration>
          <suiteXmlFiles>
            <suiteXmlFile>testng.xml</suiteXmlFile>
          </suiteXmlFiles>
          <argLine>
            -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
          </argLine>
        </configuration>
        <dependencies>
          <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${aspectj.version}</version>
            <scope>runtime</scope>
          </dependency>
        </dependencies>
      </plugin>
      <plugin>
        <groupId>io.qameta.allure</groupId>
        <artifactId>allure-maven</artifactId>
        <version>${allure.maven}</version>
        <configuration>
          <reportVersion>${allure.maven}</reportVersion>
        </configuration>
      </plugin>
    </plugins>
  </build>

<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>AllureReport_Cucumber_TestNG</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

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

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <cucumber.version>7.15.0</cucumber.version>
    <selenium.version>4.16.1</selenium.version>
    <testng.version>7.9.0</testng.version>
    <maven.compiler.plugin.version>3.12.1</maven.compiler.plugin.version>
    <maven.surefire.plugin.version>3.2.3</maven.surefire.plugin.version>
    <maven.compiler.source.version>17</maven.compiler.source.version>
    <maven.compiler.target.version>17</maven.compiler.target.version>
    <allure.junit4.version>2.25.0</allure.junit4.version>
    <aspectj.version>1.9.21</aspectj.version>
    <allure.version>2.25.0</allure.version>
    <allure.maven>2.12.0</allure.maven>
  </properties>

  <!-- Add allure-bom to dependency management to ensure correct versions of all the dependencies are used -->
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>io.qameta.allure</groupId>
        <artifactId>allure-bom</artifactId>
        <version>${allure.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <dependencies>

    <dependency>
      <groupId>io.cucumber</groupId>
      <artifactId>cucumber-java</artifactId>
      <version>${cucumber.version}</version>
    </dependency>

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

    <!-- Selenium -->
    <dependency>
      <groupId>org.seleniumhq.selenium</groupId>
      <artifactId>selenium-java</artifactId>
      <version>${selenium.version}</version>
    </dependency>

    <!-- TestNG -->
    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>${testng.version}</version>
      <scope>test</scope>
    </dependency>

    <!--Allure Cucumber Dependency-->
    <dependency>
      <groupId>io.qameta.allure</groupId>
      <artifactId>allure-cucumber7-jvm</artifactId>
      <scope>test</scope>
    </dependency>

    <!--Allure Reporting Dependency-->
    <dependency>
      <groupId>io.qameta.allure</groupId>
      <artifactId>allure-testng</artifactId>
      <scope>test</scope>
    </dependency>

  </dependencies>

  <build>
    <plugins>
      <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>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>${maven.surefire.plugin.version}</version>
        <configuration>
          <suiteXmlFiles>
            <suiteXmlFile>testng.xml</suiteXmlFile>
          </suiteXmlFiles>
          <argLine>
            -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
          </argLine>
        </configuration>
        <dependencies>
          <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${aspectj.version}</version>
            <scope>runtime</scope>
          </dependency>
        </dependencies>
      </plugin>
      <plugin>
        <groupId>io.qameta.allure</groupId>
        <artifactId>allure-maven</artifactId>
        <version>${allure.maven}</version>
        <configuration>
          <reportVersion>${allure.maven}</reportVersion>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

Step 4 – Create a Feature file

Create a folder – features within src/test/resources to create test scenarios in the 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. In this feature file. The test scenarios are written in Gherkins language.

Feature: Login to HRM Application

  Background:
    Given User is on HRMLogin page "https://opensource-demo.orangehrmlive.com/"

  @ValidCredentials
  Scenario: Login with valid credentials

    When User enters username as "Admin" and password as "admin123"
    Then User should be able to login successfully and new page open

  @InvalidCredentials
  Scenario Outline: Login with invalid credentials

    When User enters username as "<username>" and password as "<password>"
    Then User should be able to see error message "<errorMessage>"

    Examples:
      | username   | password  | errorMessage                      |
      | Admin      | admin12$$ | Invalid credentials               |
      | admin$$    | admin123  | Invalid credentials               |
      | abc123     | xyz$$     | Invalid credentials               |
      | 234        | xyz$$     | Invalid credentials!              |

Step 5 – Create the Step Definition class or Glue Code

Below is the code for the Hooks.

package com.example.definitions;

import io.cucumber.java.After;
import io.cucumber.java.Before;
import io.cucumber.java.Scenario;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

import java.time.Duration;

public class Hooks {
    protected static WebDriver driver;
    public final static int TIMEOUT = 5;

    @Before
    public void setUp() {

        ChromeOptions options = new ChromeOptions();
        options.addArguments("--start-maximized");
        driver = new ChromeDriver(options);
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(TIMEOUT));

    }

    @After
    public void tearDown(Scenario scenario) {
        try {
            String screenshotName = scenario.getName();
            if (scenario.isFailed()) {
                TakesScreenshot ts = (TakesScreenshot) driver;
                byte[] screenshot = ts.getScreenshotAs(OutputType.BYTES);
                scenario.attach(screenshot, "img/png", screenshotName);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        driver.quit();
    }

}

LoginPageDefinition

package com.example.definitions;


import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;

import org.openqa.selenium.By;
import org.testng.Assert;

public class LoginPageDefinitions {

   Hooks hooks;


    @Given("User is on HRMLogin page {string}")
    public void loginTest(String url) {

        hooks.driver.get(url);

    }

    @When("User enters username as {string} and password as {string}")
    public void goToHomePage(String userName, String passWord) {

        // login to application
        hooks.driver.findElement(By.name("username")).sendKeys(userName);
        hooks.driver.findElement(By.name("password")).sendKeys(passWord);
        hooks.driver.findElement(By.xpath("//*[@class='oxd-form']/div[3]/button")).submit();

        // go the next page
    }

    @Then("User should be able to login successfully and new page open")
    public void verifyLogin() {

        String homePageHeading = hooks.driver.findElement(By.xpath("//*[@class='oxd-topbar-header-breadcrumb']/h6")).getText();

        //Verify new page - HomePage
        Assert.assertEquals(homePageHeading,"Dashboard");

    }

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

        String actualErrorMessage = hooks.driver.findElement(By.xpath("//*[@class='orangehrm-login-error']/div[1]/div[1]/p")).getText();

        // Verify Error Message
        Assert.assertEquals(actualErrorMessage, expectedErrorMessage);

    }

}

Step 6 – Create a TestNG Cucumber Runner class

We need to create a class called Runner class to run the tests. This class will use the TestNG annotation @Test, which tells TestNG what is the test runner class.

package com.example.runner;

import org.testng.annotations.Test;
import io.cucumber.testng.AbstractTestNGCucumberTests;
import io.cucumber.testng.CucumberOptions;


@Test
@CucumberOptions(tags = "", features = {"src/test/resources/features"}, glue = {"com.example.definitions"},
        plugin = {"pretty","io.qameta.allure.cucumber7jvm.AllureCucumber7Jvm"})

public class CucumberRunnerTests extends AbstractTestNGCucumberTests{

}

Note:- @Test annotation marks this class as part of the test. So, if we will remove this annotation, the Allure Report executes CucumberRunnerTests as a separate test suite, so there will be duplicate results.

Step 7 – Create testng.xml for the project

<?xml version = "1.0"encoding = "UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name = "Suite1">
    <test name = "Test Demo">
        <classes>
            <class name = "com.example.runner.CucumberRunnerTests"/>
        </classes>
    </test>
</suite>

Step 8 – Run the Test and Generate Allure Report

To run the tests, use the below command

mvn clean test

In the below image, we can see that one test failed and four passed out of five tests.

This will create the allure-results folder with all the test reports within target folder. These files will be used to generate Allure Report.

Use the below command to generate the Allure Report

allure serve

This will generate the beautiful Allure Test Report as shown below.

Allure Report Dashboard

Categories in Allure Report

The categories tab gives you a way to create custom defect classifications to apply for test results. There are two categories of defects – Product Defects (failed tests) and Test Defects (broken tests).

Suites in Allure Report

On the Suites tab a standard structural representation of executed tests, grouped by suites and classes can be found. Here, we have 2 suits – Feature and Surefire test. Surefire tests are executed from CucumberRunnerTests.

Graphs in Allure Report

Graphs allow you to see different statistics collected from the test data: status breakdown or severity and duration diagrams.

Timeline in Allure Report

The timeline tab visualizes retrospective test execution, allure adaptors collect precise timings of tests, and here on this tab, they are arranged accordingly to their sequential or parallel timing structure.

Behaviours of Allure Report

This tab groups test results according to Epic, Feature, and Story tags.

Screenshot attached to the failed test case

Packages in Allure Report

The packages tab represents a tree-like layout of test results, grouped by different packages.

When we don’t use @Test in CucumberRunnerTests.java, then as mentioned above the Allure report will have duplicate details.

Congratulations!! We have integrated an allure report with Cucumber, Selenium, and TestNG. I hope this tutorial is useful to you.

Additional Tutorials on Allure Reports

Integration of Allure Report with Selenium and JUnit4
Integration of Allure Report with Selenium and TestNG
Gradle – Allure Report for Selenium and JUnit4
Gradle – Allure Report for Cucumber, Selenium and TestNG
Integration of Allure Report with Rest Assured and JUnit4

Allure Report with Cucumber, Selenium and JUnit4

HOME

In the previous tutorial, I have explained the Integration of the Allure Report with Selenium and JUnit4. In this tutorial, I will explain how to Integrate Allure Report with Cucumber7 and JUnit4.

Below example covers the implementation of Allure Reports in Selenium using JUnit4, Java and Maven.

  1. Prerequisite
  2. Dependency List
  3. Project Structure
  4. Implementation Steps
    1. Update Properties section in Maven pom.xml
    2. Add dependencies to POM.xml
    3. Update Build Section of pom.xml in Allure Report Project
    4. Create Feature file in src/test/resources
    5. Create the Step Definition class or Glue Code
    6. Create a Cucumber Runner class
    7. Create allure.properties in src/test/resources
    8. Run the Test and Generate Allure Report
    9. Generate Allure Report

Prerequisite

  1. Java 11 or above installed
  2. Maven installed
  3. Eclipse or IntelliJ installed
  4. Allure installed and configured

Dependency List:

  1. Selenium – 4.16.1
  2. Java 17
  3. Cucumber – 7.15.0
  4. Maven – 3.9.5
  5. Allure BOM – 2.25.0
  6. Aspectj – 1.9.21
  7. Allure Maven – 2.12.0
  8. JUnit – 4.13.2

Implementation Steps

Step 1 – Update Properties section in Maven pom.xml

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <cucumber.version>7.15.0</cucumber.version>
    <selenium.version>4.16.1</selenium.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.compiler.source.version>17</maven.compiler.source.version>
    <maven.compiler.target.version>17</maven.compiler.target.version>
    <allure.junit4.version>2.25.0</allure.junit4.version>
    <aspectj.version>1.9.21</aspectj.version>
    <allure.version>2.25.0</allure.version>
    <allure.maven>2.12.0</allure.maven>
 </properties>

Step 2 – Add dependencies to POM.xml

 <dependencies>
     
     <!--Cucumber Dependencies-->     
    <dependency>
      <groupId>io.cucumber</groupId>
      <artifactId>cucumber-java</artifactId>
      <version>${cucumber.version}</version>
    </dependency>
    
    <dependency>
      <groupId>io.cucumber</groupId>
      <artifactId>cucumber-junit</artifactId>
      <version>${cucumber.version}</version>
       <scope>test</scope>
    </dependency>
 
   <!--Selenium Dependency-->
    <dependency>
      <groupId>org.seleniumhq.selenium</groupId>
      <artifactId>selenium-java</artifactId>
      <version>${selenium.version}</version>
    </dependency>   

   <!--Hamcrest Dependency-->
    <dependency>
      <groupId>org.hamcrest</groupId>
      <artifactId>hamcrest</artifactId>
      <version>2.2</version>
      <scope>test</scope>
    </dependency>
    
   <!--Allure Cucumber Dependency-->     
      <dependency>
        <groupId>io.qameta.allure</groupId>
        <artifactId>allure-cucumber5-jvm</artifactId>
        <version>${allure.cucumber5.version}</version>
    </dependency>
    
     <!--Allure Reporting Dependency-->     
    <dependency>
        <groupId>io.qameta.allure</groupId>
        <artifactId>allure-junit4</artifactId>
        <version>${allure.junit4.version}</version>
        <scope>test</scope>
    </dependency>

  </dependencies>

Step 3 – Update Build Section of pom.xml in Allure Report Project

<build>
        <plugins>
            <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>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>${maven.surefire.plugin.version}</version>
                <configuration>
                    <argLine>
                        -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
                    </argLine>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjweaver</artifactId>
                        <version>${aspectj.version}</version>
                        <scope>runtime</scope>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
                <groupId>io.qameta.allure</groupId>
                <artifactId>allure-maven</artifactId>
                <version>${allure.maven}</version>
                <configuration>
                    <reportVersion>${allure.maven}</reportVersion>
                </configuration>
            </plugin>
        </plugins>
    </build>

<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>AllureReport_Cucumber_JUnit4</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

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

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <cucumber.version>7.15.0</cucumber.version>
        <selenium.version>4.16.1</selenium.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.compiler.source.version>17</maven.compiler.source.version>
        <maven.compiler.target.version>17</maven.compiler.target.version>
        <allure.junit4.version>2.25.0</allure.junit4.version>
        <aspectj.version>1.9.21</aspectj.version>
        <allure.version>2.25.0</allure.version>
        <allure.maven>2.12.0</allure.maven>
    </properties>

    <!-- Add allure-bom to dependency management to ensure correct versions of all the dependencies are used -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>io.qameta.allure</groupId>
                <artifactId>allure-bom</artifactId>
                <version>${allure.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>


    <dependencies>

        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-java</artifactId>
            <version>${cucumber.version}</version>
        </dependency>

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

        <!-- Selenium -->
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>${selenium.version}</version>
        </dependency>

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

        <!--Allure Cucumber Dependency-->
        <dependency>
            <groupId>io.qameta.allure</groupId>
            <artifactId>allure-cucumber7-jvm</artifactId>
            <scope>test</scope>
        </dependency>

        <!--Allure Reporting Dependency-->
        <dependency>
            <groupId>io.qameta.allure</groupId>
            <artifactId>allure-junit4</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <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>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>${maven.surefire.plugin.version}</version>
                <configuration>
                    <argLine>
                        -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
                    </argLine>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjweaver</artifactId>
                        <version>${aspectj.version}</version>
                        <scope>runtime</scope>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
                <groupId>io.qameta.allure</groupId>
                <artifactId>allure-maven</artifactId>
                <version>${allure.maven}</version>
                <configuration>
                    <reportVersion>${allure.maven}</reportVersion>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Step 4 – Create Feature file in src/test/resources

Create source folder – src/test/resources and features folder within src/test/resources to create test scenarios in 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. In this feature file, I have created a scenario for successful login and one Scenario Outline for failed login. The test scenarios are written in Gherkins language.

Feature: Login to HRM Application

  Background:
    Given User is on HRMLogin page "https://opensource-demo.orangehrmlive.com/"

  @ValidCredentials
  Scenario: Login with valid credentials

    When User enters username as "Admin" and password as "admin123"
    Then User should be able to login successfully and new page open

  @InvalidCredentials
  Scenario Outline: Login with invalid credentials

    When User enters username as "<username>" and password as "<password>"
    Then User should be able to see error message "<errorMessage>"

    Examples:
      | username   | password    | errorMessage                      |
      | Admin        | admin12$$ | Invalid credentials               |
      | admin$$     | admin123   | Invalid credentials               |
      | abc123       | xyz$$          | Invalid credentials               |
      | 234             | xyz$$         | Invalid credentials!              |

Step 5 – Create the Step Definition class or Glue Code

package com.example.definitions;

import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import org.junit.Assert;
import org.openqa.selenium.By;

public class LoginPageDefinitions {

   Hooks hooks;

    @Given("User is on HRMLogin page {string}")
    public void loginTest(String url) {

        hooks.driver.get(url);

    }

    @When("User enters username as {string} and password as {string}")
    public void goToHomePage(String userName, String passWord) {

        // login to application
        hooks.driver.findElement(By.name("username")).sendKeys(userName);
        hooks.driver.findElement(By.name("password")).sendKeys(passWord);
        hooks.driver.findElement(By.xpath("//*[@class='oxd-form']/div[3]/button")).submit();

        // go the next page
    }

    @Then("User should be able to login successfully and new page open")
    public void verifyLogin() {

        String homePageHeading = hooks.driver.findElement(By.xpath("//*[@class='oxd-topbar-header-breadcrumb']/h6")).getText();

        //Verify new page - HomePage
        Assert.assertEquals("Dashboard",homePageHeading);

    }

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

        String actualErrorMessage = hooks.driver.findElement(By.xpath("//*[@class='orangehrm-login-error']/div[1]/div[1]/p")).getText();

        // Verify Error Message
        Assert.assertEquals(expectedErrorMessage,actualErrorMessage);

    }

}

Hook.java

package com.example.definitions;

import io.cucumber.java.After;
import io.cucumber.java.Before;
import io.cucumber.java.Scenario;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

import java.time.Duration;

public class Hooks {
    protected static WebDriver driver;
    public final static int TIMEOUT = 5;

    @Before
    public void setUp() {

        ChromeOptions options = new ChromeOptions();
        options.addArguments("--start-maximized");
        driver = new ChromeDriver(options);
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(TIMEOUT));

    }

    @After
    public void tearDown(Scenario scenario) {
        try {
            String screenshotName = scenario.getName();
            if (scenario.isFailed()) {
                TakesScreenshot ts = (TakesScreenshot) driver;
                byte[] screenshot = ts.getScreenshotAs(OutputType.BYTES);
                scenario.attach(screenshot, "img/png", screenshotName);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        driver.quit();
    }
}

Step 6 – Create a Cucumber Runner class

We need to create a class called Runner class to run the tests. This class will use the JUnit annotation @RunWith(), which tells JUnit what is the test runner class.

package com.example.runner;

import org.junit.runner.RunWith;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;

@RunWith(Cucumber.class)
@CucumberOptions(tags = "", features = {"src/test/resources/features"}, glue = {"com.example.definitions"},
        plugin = {"pretty","io.qameta.allure.cucumber7jvm.AllureCucumber7Jvm"})

public class CucumberRunnerTests  {

}

allure.results.directory=target/allure-results

Step 8 – Run the Test and Generate Allure Report

To run the tests, use the below command

mvn clean test

In the below image, we can see that one test is failed and four passed out of five tests.

This will create allure-results folder with all the test report. These files will be use to generate Allure Report.

Change current directory to target directory and then use the below command to generate the Allure Report

allure serve

This will generate the beautiful Allure Test Report as shown below.

Allure Report Dashboard

It shows detail of all the test steps and the screenshot of the failed test step also as shown below.

Categories in Allure Report

Categories tab gives you the way to create custom defects classification to apply for test results. There are two categories of defects – Product Defects (failed tests) and Test Defects (broken tests).

Suites in Allure Report

On the Suites tab a standard structural representation of executed tests, grouped by suites and classes can be found.

Graphs in Allure Report

Graphs allow you to see different statistics collected from the test data: statuses breakdown or severity and duration diagrams.

Timeline in Allure Report

Timeline tab visualizes retrospective of tests execution, allure adaptors collect precise timings of tests, and here on this tab they are arranged accordingly to their sequential or parallel timing structure.

Behaviors of Allure Report

This tab groups test results according to Epic, Feature and Story tags.

Packages in Allure Report

Packages tab represents a tree-like layout of test results, grouped by different packages.

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

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.

How to add Screenshot to Cucumber ExtentReports

Last Updated On

HOME

The previous tutorial explained the generation of Extent Report 5 for Cucumber7 and TestNG. This tutorial explains how to add screenshots to the Extent Report.

Table of Contents

  1. Project Structure
    1. Add Screenshot configuration in extent.properties
    2. Add a method to capture the screenshot

Project Structure

To set up the above project, please refer to this tutorial – ExtentReports Version 5 for Cucumber 7 and TestNG.

We want to add screenshots of failed tests to the Extent Report Version 5.

Step 1 – Add Screenshot configuration in extent.properties

extent.reporter.spark.start=true
extent.reporter.spark.out=Reports/Spark.html

#FolderName
basefolder.name=ExtentReports/SparkReport_
basefolder.datetimepattern=d_MMM_YY HH_mm_ss

#Screenshot
screenshot.dir=/Screenshots/
screenshot.rel.path=../Screenshots/

In the above example, we have provided the name “ExtentReports/SparkReport_”. It means that a folder starts with the name “SparkReport_” under the “ExtentReports” folder. The date-time pattern we have provided in another format is the basis of a valid pattern. It will concatenate with the folder name to generate a unique folder for each execution.

As seen in the image above, the “Reports” and “Screenshots” folders get created inside the new folder of SparkReports_. If we look inside the folder, we can see that the report was generated.

We can browse the screenshot folder to see all the screenshots taken during each step. Additionally, screenshots will be generated and named automatically.

Step 2 – Add a method to capture the screenshot

@After
public static void tearDown(Scenario scenario) {

		//validate if scenario has failed
		if(scenario.isFailed()) {
			final byte[] screenshot = ((TakesScreenshot) driver.getScreenshotAs(OutputType.BYTES);
			scenario.attach(screenshot, "image/png", scenario.getName()); 
		}	

In the preceding example, the tearDown() method accepts a Scenario type object. The Scenario can be found within the io.cucumber. We used Selenium’s standard screenshot feature within the method. As an example, we’d like to read the file as a byte[] type. As a parameter, the attach method accepts byte[] type objects. Scenario.attach also includes a screenshot with each step of the scenario. To get the complete project, please refer to this tutorial – ExtentReports Version 5 for Cucumber 6 and TestNG.

The updated Hooks class will be as shown below:

import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import com.example.utils.HelperClass;
import io.cucumber.java.After;
import io.cucumber.java.Before;
import io.cucumber.java.Scenario;

public class Hooks {
	
	@Before
    public static void setUp() {

       HelperClass.setUpDriver();
    }

	@After
	public static void tearDown(Scenario scenario) {

		//validate if scenario has failed
		if(scenario.isFailed()) {
			final byte[] screenshot = ((TakesScreenshot) HelperClass.getDriver()).getScreenshotAs(OutputType.BYTES);
			scenario.attach(screenshot, "image/png", scenario.getName()); 
		}	
		
		HelperClass.tearDown();
	}
}

Let’s open the report and view the report. As you can see, besides the scenario, an attachment sign is available, which means something attaches to the scenario. As we have only one failed step, only one screenshot has been captured, as seen in the above image. Right-click on Spark.html and select Open with Web Browser.

The report also has a summary section that displays the summary of the execution. The summary includes the overview of the pass/fail using a pictogram, start time, end time, and pass/fail details of features as shown in the image below.

Congratulations!! We can attach screenshots of the failed tests. Happy Learning!!

Gradle – Extent Report Version 5 for Cucumber, Selenium, and TestNG
Integration of Allure Report with Rest Assured and JUnit4
ExtentReports Version 5 for Cucumber 6 and JUnit4
PDF ExtentReport for Cucumber and TestNG

Integration of Allure Report with Rest Assured and TestNG

HOME

In the previous tutorial, I explained the Integration of the Allure Report with Rest Assured with JUnit4. In this tutorial, I will explain how to Integrate Allure Report with Rest Assured and TestNG.

The below example covers the implementation of Allure Report for Rest API using Rest Assured, TestNG, Java, and Maven.

Prerequisite

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

Dependency List:

  1. Java 17
  2. Maven – 3.9.6
  3. Allure Report – 2.14.0
  4. Allure Rest Assured – 2.25.0
  5. Allure TestNG – 2.25.0
  6. Aspectj – 1.9.21
  7. Json – 20231013
  8. Maven Compiler Plugin – 3.12.1
  9. Maven Surefire Plugin – 3.2.3

Implementation Steps

  1. Update Properties section in Maven pom.xml
  2. Add Rest Assured, Allure-Rest Assured and Allure-TetNG dependencies in POM.xml
  3. Update Build Section of pom.xml in Allure Report Project.
  4. Create the Test Code for the testing of REST API under src/test/java
  5. Create TestNG.xml for the project
  6. Run the Tests and Generate Allure Report

Step 1 – Update Properties section in Maven pom.xml

<properties>
        <hamcrest.version>1.3</hamcrest.version>
        <allure.rest.assured.version>2.25.0</allure.rest.assured.version>
        <json.version>20231013</json.version>
        <maven.compiler.plugin.version>3.12.1</maven.compiler.plugin.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <aspectj.version>1.9.21</aspectj.version>
        <maven.surefire.plugin.version>3.2.3</maven.surefire.plugin.version>
        <allure.maven.version>2.12.0</allure.maven.version>
        <allure.testng.version>2.25.0</allure.testng.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 </properties>

Step 2 – Add the Allure-Rest Assured dependency

 <!--Allure Reporting Dependency-->   
   <dependency>
      <groupId>io.qameta.allure</groupId>
      <artifactId>allure-rest-assured</artifactId>
      <version>${allure.rest-assured.version}</version>
   </dependency>

Add other dependencies like Rest Assured and Allure-TetNG dependencies in POM.xml

 <dependencies>

        <!-- Hamcrest Dependency -->
        <dependency>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-all</artifactId>
            <version>${hamcrest.version}</version>
            <scope>test</scope>
        </dependency>

        <!-- JSON Dependency -->
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>${json.version}</version>
        </dependency>

        <!-- Allure TestNG Dependency -->
        <dependency>
            <groupId>io.qameta.allure</groupId>
            <artifactId>allure-testng</artifactId>
            <version>${allure.testng.version}</version>
        </dependency>

        <!-- Allure Rest-assured Dependency-->
        <dependency>
            <groupId>io.qameta.allure</groupId>
            <artifactId>allure-rest-assured</artifactId>
            <version>${allure.rest.assured.version}</version>
        </dependency>

    </dependencies>

Step 3 – Update the Build Section of pom.xml in the Allure Report Project

 <build>
        <plugins>
            <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>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>${maven.surefire.plugin.version}</version>
                <configuration>
                    <suiteXmlFiles>
                        <suiteXmlFile>testng.xml</suiteXmlFile>
                    </suiteXmlFiles>
                    <argLine>
                        -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
                    </argLine>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjweaver</artifactId>
                        <version>${aspectj.version}</version>
                    </dependency>
                </dependencies>
            </plugin>

             <plugin>
                <groupId>io.qameta.allure</groupId>
                <artifactId>allure-maven</artifactId>
                <version>${allure.maven.version}</version>
                <configuration>
                    <reportVersion>${allure.maven.version}</reportVersion>
                </configuration>
            </plugin>

        </plugins>
    </build>
</project>

Step 4 – Create the Test Code for the testing of REST API under src/test/java

To see our request and response in more detail using Rest Assured, we need to add a line to our Rest Assured tests. This will provide the request and response details in the report.

 .filter(new AllureRestAssured())
import io.qameta.allure.*;
import io.qameta.allure.restassured.AllureRestAssured;
import io.restassured.http.ContentType;
import org.json.JSONObject;
import org.testng.annotations.Test;
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.equalTo;

@Epic("REST API Regression Testing using TestNG")
@Feature("Verify CRUID Operations on User module")
public class RestAPITests {

    @Test(description = "To get the details of user with id 3", priority = 0)
    @Story("GET Request with Valid User")
    @Severity(SeverityLevel.NORMAL)
    @Description("Test Description : Verify the details of user of id-3")
    public void verifyUser() {

        // Given
        given()

                .filter(new AllureRestAssured())
                // When
                .when()
                .get("https://reqres.in/api/users/3")

                // Then
                .then()
                .statusCode(200)
                .statusLine("HTTP/1.1 200 OK")

                // To verify user of id 3
                .body("data.email", equalTo("emma.wong@reqres.in"))
                .body("data.first_name", equalTo("Emma"))
                .body("data.last_name", equalTo("Wong"));
    }

    @Test(description = "To create a new user", priority = 1)
    @Story("POST Request")
    @Severity(SeverityLevel.NORMAL)
    @Description("Test Description : Verify the creation of a new user")
    public void createUser() {

        JSONObject data = new JSONObject();

        data.put("name", "RestAPITest");
        data.put("job", "Testing");

        // GIVEN
        given()

                .filter(new AllureRestAssured())
                .contentType(ContentType.JSON)
                .body(data.toString())

                // WHEN
                .when()
                .post("https://reqres.in/api/users")

                // THEN
                .then()
                .statusCode(201)
                .body("name", equalTo("RestAPITest"))
                .body("job", equalTo("Testing"));

    }

}

Step 5 – Create testng.xml for the project

<?xml version = "1.0"encoding = "UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name = "Suite1">
    <test name = "TestNG Test Demo">
        <classes>
            <class name = "org.example.RestAPITests"/>
        </classes>
    </test>
</suite>

Step 6 – Run the Test and Generate Allure Report

To run the tests, use the below command

mvn clean test

In the below image, we can see that all three tests are passed.

This will create the allure-results folder with all the test reports. These files will be used to generate the Allure Report.

To create an Allure Report, use the below command

allure serve

This will generate the beautiful Allure Test Report as shown below.

Allure Report Dashboard

The overview page hosts several default widgets representing the basic characteristics of your project and test environment.

Categories in Allure Report

The categories tab gives you a way to create custom defect classifications to apply for test results. There are two categories of defects – Product Defects (failed tests) and Test Defects (broken tests).

Suites in Allure Report

On the Suites tab a standard structural representation of executed tests, grouped by suites and classes, can be found.

View test history

Each time you run the report from the command line with the mvn clean test command, a new result JSON file will get added to the allure-results folder. Allure can use those files to include a historical view of your tests. Let’s give that a try.

To get started, run mvn clean test a few times and watch how the number of files in the allure-reports folder grows.

Now go back to view your report. Select Suites from the left nav, select one of your tests and click Retries in the right pane. You should see the history of test runs for that test:

Graphs in Allure Report

Graphs allow you to see different statistics collected from the test data: status breakdown or severity and duration diagrams.

Timeline in Allure Report

Timeline tab visualizes retrospective of tests execution, allure adaptors collect precise timings of tests, and here on this tab, they are arranged accordingly to their sequential or parallel timing structure.

Behaviors of Allure Report

This tab groups test results according to Epic, Feature, and Story tags.

Packages in Allure Report

The packages tab represents a tree-like layout of test results, grouped by different packages.

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

Cucumber Reports

HOME

Sharing Cucumber test results with your colleagues is not easy. To make things easier, the Cucumber team has created a free, cloud-based service for sharing reports across the organization. The Cucumber Reports service, which is currently in early beta, allows you to configure Cucumber (currently only in Ruby or Java flavours) to upload the results of a Cucumber run to the cloud. You can then access them through your browser, which will render them using the same HTML formatter as on the desktop.

Chapter 1 Cucumber Reports – HTML, XML, JSON
Chapter 2 Cucumber Report Service
Chapter 3 Implemention of ‘Masterthought’ Reports in Cucumber with TestNG
Chapter 4 Implemention of ‘Masterthought’ Reports in Cucumber with JUnit4

ExtentReports Version 5 for Cucumber 6 and JUnit4

HOME

The previous tutorial explained the steps to generate ExtentReports for Cucumber with TestNG. We can generate ExtentReports for Cucumber with JUnit4 also. This tutorial explains the steps that need to be followed to generate an ExtentReports Version5.

Pre-Requisite:

  1. Java 8 or higher is needed for ExtentReport5
  2. Maven or Gradle
  3. JAVA IDE (like Eclipse, IntelliJ, or soon)
  4. JUnit4 installed
  5. Cucumber Eclipse plugin (in case using Eclipse)

Project Structure

Step 1 – Add Maven dependencies to the POM

Add ExtentReport dependency

<dependency>
    <groupId>com.aventstack</groupId>
    <artifactId>extentreports</artifactId>
    <version>5.0.9</version>
</dependency>

Add tech grasshopper maven dependency for Cucumber

<dependency>
    <groupId>tech.grasshopper</groupId>
    <artifactId>extentreports-cucumber6-adapter</artifactId>
    <version>2.13.0</version>
</dependency>

The complete POM.xml will look like as shown below with other Selenium and JUnit4 dependencies.

 <properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<selenium.version>4.3.0</selenium.version>
		<cucumber.version>6.11.0</cucumber.version>
		<extentreports.cucumber6.adapter.version>2.13.0</extentreports.cucumber6.adapter.version>
		<extentreports.version>5.0.9</extentreports.version>
		<junit.version>4.13.2</junit.version>
		<apache.common.version>2.4</apache.common.version>
		<webdrivermanager.version>5.2.1</webdrivermanager.version>
		<maven.compiler.plugin.version>3.10.1</maven.compiler.plugin.version>
		<maven.surefire.plugin.version>3.0.0-M7</maven.surefire.plugin.version>
		<maven.compiler.source.version>11</maven.compiler.source.version>
		<maven.compiler.target.version>11</maven.compiler.target.version>
	</properties>

	<dependencies>

		<dependency>
			<groupId>io.cucumber</groupId>
			<artifactId>cucumber-java</artifactId>
			<version>${cucumber.version}</version>
		</dependency>

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

		<!-- https://mvnrepository.com/artifact/tech.grasshopper/extentreports-cucumber6-adapter -->
		<dependency>
			<groupId>tech.grasshopper</groupId>
			<artifactId>extentreports-cucumber6-adapter</artifactId>
			<version>${extentreports.cucumber6.adapter.version}</version>
		</dependency>

		<!-- Extent Report -->
		<dependency>
			<groupId>com.aventstack</groupId>
			<artifactId>extentreports</artifactId>
			<version>${extentreports.version}</version>
		</dependency>

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

		<!-- Apache Common -->
		<dependency>
			<groupId>org.apache.directory.studio</groupId>
			<artifactId>org.apache.commons.io</artifactId>
			<version>${apache.common.version}</version>
		</dependency>
		
		<!-- Selenium -->
		<dependency>
			<groupId>org.seleniumhq.selenium</groupId>
			<artifactId>selenium-java</artifactId>
			<version>${selenium.version}</version>
		</dependency>

		<!-- Web Driver Manager -->
		<dependency>
			<groupId>io.github.bonigarcia</groupId>
			<artifactId>webdrivermanager</artifactId>
			<version>${webdrivermanager.version}</version>
		</dependency>
	</dependencies>
	
	<build>
     <plugins>
       <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> <!--For JAVA 8 use 1.8-->
			 <target>${maven.compiler.target.version}</target> <!--For JAVA 8 use 1.8-->
            <encoding>UTF-8</encoding>          
         </configuration>
       </plugin>                
       </plugins>
   </build>

</project>

Step 2: Create a feature file in src/test/resources

Below is a sample feature file

Feature: Login to HRM Application 
 
  @ValidCredentials
   Scenario: Login with valid credentials
     
    Given User is on HRMLogin page "https://opensource-demo.orangehrmlive.com/"
    When User enters username as "Admin" and password as "admin123"
    Then User should be able to login successfully and new page open
    
   @InvalidCredentials
   Scenario Outline: Login with invalid credentials
     
    Given User is on HRMLogin page "https://opensource-demo.orangehrmlive.com/"
    When User enters username as "<username>" and password as "<password>"
    Then User should be able to see error message "<errorMessage>"
    
  Examples:
  | username   | password  | errorMessage                      |
  |            | abc       | Username cannot be empty          |
  | admin      |           | Password cannot be empty          |
  |            |           | Username cannot be empty          |
  | admin      | Admin123  | Invalid credentials               |
  
   
  @ForgetPassword  
   Scenario: Verify Forget Password Functionality
   
    Given User is on HRMLogin page "https://opensource-demo.orangehrmlive.com/"
    When User clicks on Forgot your password link
    Then User should be able to navigate to new page of title "Forgot Your Password?"

Step 3: Create extent.properties file in src/test/resources

We need to create the extent.properties file at the src/test/resources folder for the grasshopper extent report adapter to recognize it. Using a property file for reporting is quite helpful if you want to define several different properties.

Let’s enable spark report in an extent properties file:

extent.reporter.spark.start=true
extent.reporter.spark.out=Reports/Spark.html

#FolderName
basefolder.name=ExtentReports/SparkReport_
basefolder.datetimepattern=d_MMM_YY HH_mm_ss

#Screenshot
screenshot.dir=/Screenshots/
screenshot.rel.path=../Screenshots/

Step 4: Create a Helper class in src/main/java

We have used Page Object Model with Cucumber and TestNG.

Create a Helper class where we are initializing the web driver, initializing the web driver wait, defining the timeouts, and creating a private constructor of the class, it will declare the web driver, so whenever we create an object of this class, a new web browser is invoked. We are using a setter and getter method to get the object of Chromedriver with the help of a private constructor itself within the same class.

HelperClass

import java.time.Duration;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.WebDriverWait;
import io.github.bonigarcia.wdm.WebDriverManager;

public class HelperClass {
	
	private static HelperClass helperClass;
	
	private static WebDriver driver;
	private static WebDriverWait wait;
    public final static int TIMEOUT = 10;
		
	 private HelperClass() {
		 
			WebDriverManager.chromedriver().setup();
	    	driver = new ChromeDriver();
	        wait = new WebDriverWait(driver, Duration.ofSeconds(TIMEOUT));
	        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(TIMEOUT));
	        driver.manage().window().maximize();

	 }      
	    	
    public static void openPage(String url) {
        driver.get(url);
    }
	
	public static WebDriver getDriver() {
		return driver;		
	}
	
	public static void setUpDriver() {
		
		if (helperClass==null) {
			
			helperClass = new HelperClass();
		}
	}
	
	 public static void tearDown() {
		 
		 if(driver!=null) {
			 driver.close();
			 driver.quit();
		 }
		 
		 helperClass = null;
	 } 	
}

Step 5: Create Locator classes in src/main/java

Create a locator class for each page that contains the detail of the locators of all the web elements. Here, I’m creating 3 locator classes – LoginPageLocators, HomePageLocators, and ForgetPasswordPageLocators.

LoginPageLocators

import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;

public class LoginPageLocators {

	@FindBy(name = "txtUsername")
    public WebElement userName;
 
    @FindBy(name = "txtPassword")
    public WebElement password;
 
    @FindBy(id = "logInPanelHeading")
    public WebElement titleText;
 
    @FindBy(id = "btnLogin")
    public WebElement login;
 
    @FindBy(id = "spanMessage")
    public  WebElement errorMessage;
    
    @FindBy(xpath = "//*[@id='forgotPasswordLink']/a")
    public  WebElement forgotPasswordLink;
  
}

HomePageLocators

import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;

public class HomePageLocators {

	@FindBy(id = "welcome")
	public  WebElement homePageUserName;
 
}

ForgetPasswordPageLocators

import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;

public class ForgetPasswordPageLocators {
	
	@FindBy(xpath = "//*[@id='content']/div[1]/div[2]/h1")
    public WebElement forgotPasswordPageHeading;
	
}

Step 6: Create Action classes in src/main/java

Create the action classes for each web page. These action classes contain all the methods needed by the step definitions. In this case, I have created 3 action classes – LoginPageActions, HomePageActions, and ForgetPasswordPageActions.

LoginPageActions

In this class, the very first thing will do is to create the object of LoginPageLocators class so that we should be able to access all the PageFactory elements. Secondly, create a public constructor of LoginPageActions class.

import org.openqa.selenium.support.PageFactory;
import com.example.junit.locators.LoginPageLocators;
import com.example.junit.utils.HelperClass;

public class LoginPageActions {

	LoginPageLocators loginPageLocators = null; 
	
    public LoginPageActions() {

    	this.loginPageLocators = new LoginPageLocators();
		PageFactory.initElements(HelperClass.getDriver(),loginPageLocators);
	}

	// Set user name in textbox
    public void setUserName(String strUserName) {
    	loginPageLocators.userName.sendKeys(strUserName);
    }
 
    // Set password in password textbox
    public void setPassword(String strPassword) {
    	loginPageLocators.password.sendKeys(strPassword);
    }
 
    // Click on login button
    public void clickLogin() {
    	loginPageLocators.login.click();
    }
 
    // Get the title of Login Page
    public String getLoginTitle() {
        return loginPageLocators.titleText.getText();
    }
       
    // Get the title of Login Page
    public String getErrorMessage() {
        return loginPageLocators.errorMessage.getText();
    }
    
    // Click on forgotYourPassword Link
    public void clickOnForgotPasswordLink() {
    	loginPageLocators.forgotPasswordLink.click();
    }
 
    public void login(String strUserName, String strPassword) {
 
        // Fill user name
        this.setUserName(strUserName);
 
        // Fill password
        this.setPassword(strPassword);
 
        // Click Login button
        this.clickLogin();
 
    }
}

HomePageActions

import org.openqa.selenium.support.PageFactory;
import com.example.junit.locators.HomePageLocators;
import com.example.junit.utils.HelperClass;

public class HomePageActions {

	HomePageLocators homePageLocators = null;
   
	public HomePageActions() {
    	
		this.homePageLocators = new HomePageLocators();

		PageFactory.initElements(HelperClass.getDriver(),homePageLocators);
    }

    // Get the User name from Home Page
    public String getHomePageText() {
        return homePageLocators.homePageUserName.getText();
    }

}

ForgetPasswordPageActions

import org.openqa.selenium.support.PageFactory;
import com.example.junit.locators.ForgetPasswordPageLocators;
import com.example.junit.utils.HelperClass;

public class ForgetPasswordPageActions {
	
	ForgetPasswordPageLocators forgetPasswordPageLocators = null;
	
	public ForgetPasswordPageActions() {
		this.forgetPasswordPageLocators = new ForgetPasswordPageLocators();
		
		PageFactory.initElements(HelperClass.getDriver(), forgetPasswordPageLocators);
	}

	public String getHeading() {
				return forgetPasswordPageLocators.forgotPasswordPageHeading.getText();
		
	}
}

Step 7: Create Step Definition file in src/test/java

Create the corresponding Step Definition file of the feature file.

LoginPageDefinitions

import org.junit.Assert;
import com.example.junit.actions.ForgetPasswordPageActions;
import com.example.junit.actions.HomePageActions;
import com.example.junit.actions.LoginPageActions;
import com.example.junit.utils.HelperClass;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;

public class LoginPageDefinitions{
	
	LoginPageActions objLogin = new LoginPageActions();
    HomePageActions objHomePage = new HomePageActions();
    ForgetPasswordPageActions objForgotPasswordPage = new ForgetPasswordPageActions();
		
    @Given("User is on HRMLogin page {string}")
    public void loginTest(String url) {
    	
    	HelperClass.openPage(url);
 
    }
 
    @When("User enters username as {string} and password as {string}")
    public void goToHomePage(String userName, String passWord) {
 
        // login to application
        objLogin.login(userName, passWord);
 
        // go the next page
        
    }
    
    @When("User clicks on Forgot your password link")
    public void clickOnForgotPasswordLink() {
    	
    	objLogin.clickOnForgotPasswordLink();
    	
    }
   
    @Then("User should be able to login successfully and new page open")
    public void verifyLogin() {
 
        // Verify home page
        Assert.assertTrue(objHomePage.getHomePageText().contains("Welcome"));
 
    }
    
    @Then("User should be able to see error message {string}")
    public void verifyErrorMessage(String expectedErrorMessage) {
 
        // Verify home page
        Assert.assertEquals(objLogin.getErrorMessage(),expectedErrorMessage);
 
    }
    
    @Then("User should be able to navigate to new page of title {string}")
    public void verifyForgotPasswordPage(String heading) {
    	
    	Assert.assertEquals(objForgotPasswordPage.getHeading(),heading);
    	
    }
     
}

Step 8: Create Hook class in src/test/java

Create the hook class that contains the Before and After hook. @Before hook contains the method to call the setup driver which will initialize the chrome driver. This will be run before any test.

After Hook – Here will call the tearDown method.

import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import com.example.junit.utils.HelperClass;
import io.cucumber.java.After;
import io.cucumber.java.Before;
import io.cucumber.java.Scenario;

public class Hooks {
	
	@Before
    public static void setUp() {

       HelperClass.setUpDriver();
    }
	
	@After
	public static void tearDown(Scenario scenario) {

		//validate if scenario has failed
		if(scenario.isFailed()) {
			final byte[] screenshot = ((TakesScreenshot) HelperClass.getDriver()).getScreenshotAs(OutputType.BYTES);
			scenario.attach(screenshot, "image/png", scenario.getName()); 
		}	
	
		HelperClass.tearDown();
	}
}

Step 9: Create a Cucumber Test Runner class in src/test/java

Add the extent report cucumber adapter to the runner class’s CucumberOption annotation. It is an important component of the configuration. It also ensures that the cucumber runner class recognizes and launches the extent report adapter for the cucumber. Please add the following text as a plugin to the CucumberOptions as described below.

plugin = {"com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter:"}

This is how your runner class should look after being added to our project. Moreover, be sure to keep the colon “:” at the end.

import io.cucumber.junit.Cucumber;
import org.junit.runner.RunWith;
import io.cucumber.junit.CucumberOptions;

@RunWith(Cucumber.class)
@CucumberOptions(tags = "", features = "src/test/resources/features/LoginPage.feature", glue = "com.example.junit.definitions",
plugin = {"com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter:"})

public class CucumberRunnerTests {

}

Step 10: Execute the code

Right Click on the Runner class and select Run As -> JUnit Test.

Below is the screenshot of the Console. 

Step 11: View ExtentReport

Refresh the project and will see a new folder – Report. The ExtentReport will be present in that folder with the name Spark.html.

Right-click on Spark.html and select open with Web Browser.

The report also has a summary section that displays the summary of the execution. The summary includes the overview of the pass/fail using a pictogram, start time, end time, and pass/fail details of features as shown in the image below.

Click on the first icon present on the left side of the report. To view the details about the steps, click on the scenarios. Clicking on the scenario will expand, showing off the details of the steps of each scenario. As we can see that a screenshot is attached to the failed tests here.

Congratulation!! We are able to create an Extent Report for Cucumber and JUnit4. Happy Learning!!!

Serenity Emailable Report in Gradle

HOME

In this tutorial, I will generate an emailable Serenity Report for Gradle project. In the previous tutorial, I have explained the Generation of Serenity Emailable Report in Maven Project.

Pre-Requisite

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

This framework consists of:

  1. Serenity – 2.6.0
  2. Serenity Cucumber – 2.6.0
  3. Java 11
  4. JUnit – 4.13.2
  5. Gradle – 7.2

Steps to create Serenity Emailable Report

To setup a Gradle project for the testing of web application using Cucumber and JUnit4, please refer this tutorial (Step 1 to 3)

Update buildscript section of build.gradle file.

buildscript {
    repositories {
        mavenLocal()
        jcenter()
    }
    dependencies {
        classpath("net.serenity-bdd:serenity-gradle-plugin:2.4.24")
        classpath("net.serenity-bdd:serenity-single-page-report:2.4.24")
    }
}

Add serenity section in build.gradle.

serenity {
    reports = ["single-page-html"]
}

The complete build.gradle for the project will look like as shown below

defaultTasks 'clean', 'test', 'aggregate'

repositories {
    mavenLocal()
    jcenter()
}

buildscript {
    repositories {
        mavenLocal()
        jcenter()
    }
    dependencies {
        classpath("net.serenity-bdd:serenity-gradle-plugin:2.4.24")
        classpath("net.serenity-bdd:serenity-single-page-report:2.4.24")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'net.serenity-bdd.aggregator'

sourceCompatibility = 11
targetCompatibility = 11

serenity {
    reports = ["single-page-html"]
}

dependencies {
   
    testImplementation 'net.serenity-bdd:serenity-core:2.6.0'
    testImplementation 'net.serenity-bdd:serenity-cucumber6:2.6.0'
    testImplementation 'net.serenity-bdd:serenity-screenplay:2.6.0'
    testImplementation 'net.serenity-bdd:serenity-screenplay-webdriver:2.6.0'
    testImplementation 'junit:junit:4.13.1'
}

test {
    testLogging.showStandardStreams = true
    systemProperties System.getProperties()
}

gradle.startParameter.continueOnFailure = true

test.finalizedBy(aggregate)

Execute the test suite by using the below command.

gradle test

This will generate only index.html not serenity-summary.html (emailable) report.

To generate single page html report, we need to invoke the report task.

gradle reports

Below is the image of serenity-summary.html report.

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

How to manage screenshots in Serenity Report

HOME

Serenity provides a wide range of options to manage screenshots in the report. By default, Serenity has set option serenity.take.screenshots=BEFORE_AND_AFTER_EACH_STEP, which means the screenshot is saved before and after each step as shown in the below image. Before this tutorial, refer to the previous tutorial on How to generate Serenity Report.

However, recording many screenshots can slow down test execution. So, maybe we like to record the screenshot of failed steps in the scenario. To achieve this flexibility, configure serenity.take.screenshots property in serenity.properties file.

There are various other types of options for managing screenshots in Serenity Report. This property can take the following values:

  1. FOR_EACH_ACTION: Saves a screenshot at every web element action (like click(), typeAndEnter(), type(), typeAndTab() etc.).
  2. BEFORE_AND_AFTER_EACH_STEP: Saves a screenshot before and after every step.
  3. AFTER_EACH_STEP: Saves a screenshot after every step
  4. FOR_FAILURES: Saves screenshots only for failing steps.
  5. DISABLED: Doesn’t save screenshots for any steps.

In the below option, I have used FOR_FAILURES option in the serenity.properties file.

serenity.project.name = Serenity and Cucumber Report Demo
current.target.version = sprint-1
serenity.take.screenshots = FOR_FAILURES

Below is the screenshot of the passed test case. We can see that there is no screenshot attached to any of the test steps.

Below is the screenshot of the failed test case. We can see that there is a screenshot attached to the failed test step only, not all the test steps. In below example, it is a scenario outline with four different test data. Out of four, only one set of test data has failed. So, the screenshot is generated for the failed step of that particular test data.

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