Parallel Execution of Cucumber with Serenity and JUnit5

HOME

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

Starting with version 3.6.0 is possible to run the Cucumber scenarios in parallel.

We need to mention these in the junit-platform.properties to run the Cucumber scenarios parallelly.

cucumber.execution.parallel.enabled=true
cucumber.execution.parallel.config.strategy=fixed
cucumber.execution.parallel.config.fixed.parallelism=2
cucumber.plugin=io.cucumber.core.plugin.SerenityReporterParallel

Dependency List:

  1. Serenity – 4.0.18
  2. Serenity Cucumber – 4.0.18
  3. JUnit Jupiter – 5.9.2
  4. Java 17
  5. Maven – 3.8.1
  6. Maven Compiler Plugin – 3.11.0
  7. Maven Surefire Plugin – 3.2.1
  8. Maven FailSafe Plugin – 3.2.1

Project Structure

Step 1- Download and Install Java

Click here to know How to install Java.

Step 2 – Download and setup Eclipse IDE on the system

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

Step 3 – Setup Maven and create a new Maven Project

Click here to know How to install Maven.

Click here to know How to create a Maven project

Below is the Maven project structure. Here,

Group Id – org.example
Artifact Id – ParallelTests_Serenity_Cucumber_Junit5_Demo
Version – 0.0.1-SNAPSHOT
Package – org.example. ParallelTests_Serenity_Cucumber_Junit5_Demo

Step 4 – Update Properties section in Maven pom.xml

 <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <serenity.version>4.0.18</serenity.version>
        <serenity.cucumber.version>4.0.18</serenity.cucumber.version>
        <junit.platform.version>1.10.0</junit.platform.version>
        <cucumber.version>7.14.0</cucumber.version>
        <maven.compiler.plugin.version>3.11.0</maven.compiler.plugin.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <maven.surefire.plugin.version>3.2.1</maven.surefire.plugin.version>
        <maven.failsafe.plugin.version>3.2.1</maven.failsafe.plugin.version>
    </properties>

Step 5 – Add dependencies to POM.xml

<dependencies>

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

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

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

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

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

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

    </dependencies>

Step 6 – Update the Build Section of pom.xml

 <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>${maven.surefire.plugin.version}</version>
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>${maven.failsafe.plugin.version}</version>
                <configuration>
                    <includes>
                        <include>**/*.java</include>
                    </includes>
                    <parallel>methods</parallel>
                    <useUnlimitedThreads>true</useUnlimitedThreads>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven.compiler.plugin.version}</version>
                <configuration>
                    <source>${maven.compiler.source}</source>
                    <target>${maven.compiler.target}</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>net.serenity-bdd.maven.plugins</groupId>
                <artifactId>serenity-maven-plugin</artifactId>
                <version>${serenity.version}</version>
                <dependencies>
                    <dependency>
                        <groupId>net.serenity-bdd</groupId>
                        <artifactId>serenity-single-page-report</artifactId>
                        <version>${serenity.version}</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <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>

The complete POM.xml looks like as shown below:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>ParallelTests_Serenity_Cucumber_JUnit5_Demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <serenity.version>4.0.18</serenity.version>
        <serenity.cucumber.version>4.0.18</serenity.cucumber.version>
        <junit.platform.version>1.10.0</junit.platform.version>
        <cucumber.version>7.14.0</cucumber.version>
        <maven.compiler.plugin.version>3.11.0</maven.compiler.plugin.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <maven.surefire.plugin.version>3.2.1</maven.surefire.plugin.version>
        <maven.failsafe.plugin.version>3.2.1</maven.failsafe.plugin.version>
    </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-junit5</artifactId>
            <version>${serenity.version}</version>
        </dependency>

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

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

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

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

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>${maven.surefire.plugin.version}</version>
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>${maven.failsafe.plugin.version}</version>
                <configuration>
                    <includes>
                        <include>**/*.java</include>
                    </includes>
                    <parallel>methods</parallel>
                    <useUnlimitedThreads>true</useUnlimitedThreads>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven.compiler.plugin.version}</version>
                <configuration>
                    <source>${maven.compiler.source}</source>
                    <target>${maven.compiler.target}</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>net.serenity-bdd.maven.plugins</groupId>
                <artifactId>serenity-maven-plugin</artifactId>
                <version>${serenity.version}</version>
                <dependencies>
                    <dependency>
                        <groupId>net.serenity-bdd</groupId>
                        <artifactId>serenity-single-page-report</artifactId>
                        <version>${serenity.version}</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <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 7 – Create a feature file in src/test/resources

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

Feature: Login to HRM

  @ValidCredentials
  Scenario: Login with valid credentials

    Given User is on Home page
    When User enters username as "Admin"
    And User enters password as "admin123"
    Then User should be able to login successfully

  @InValidCredentials
  Scenario: Login with invalid credentials

    Given User is on Home page
    When User enters username as "Admin1"
    And User enters password as "Admin123"
    Then User should be able to see error message "Invalid credentials"

  @BlankUsername
  Scenario: Login with blank username

    Given User is on Home page
    When User enters username as ""
    And User enters password as "Admin123"
    Then User should be able to see error message "Required" below username

Step 8 – Create the Step pages for StepDefinition class

In Serenity, tests are broken down into reusable steps. An important principle behind Serenity is the idea that it is easier to maintain a test that uses several layers of abstraction to hide the complexity behind different parts of a test. So, in Step class, we will declare the locators of the web elements and the actions performed on these web elements.

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

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

StepLoginPage

import net.serenitybdd.core.pages.PageObject;
import net.serenitybdd.core.pages.WebElementFacade;
import net.thucydides.core.annotations.Step;
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[1]/div/span")
    WebElementFacade missingUsername;

    @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("Error Message for missing username")
    public String missingUsernameErrorMessage() {
        String actualErrorMessage = missingUsername.getText();
        return actualErrorMessage;
    }

}

StepHomePage

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

public class StepHomePage extends PageObject {

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

    @Step("Successful login")
    public String getHomPageTitle() {
        String dashboardTitle = dashboardText.getText();
       return dashboardTitle;


    }
}

Step 9 – Create the Step Definition class or Glue Code

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

LoginPageDefinitions

package org.example.definitions;

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.example.steps.StepHomePage;
import org.example.steps.StepLoginPage;
import static org.junit.jupiter.api.Assertions.*;

public class LoginPageDefinitions {

    @Steps
    StepLoginPage loginPage;

    @Steps
    StepHomePage homePage;

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

    }

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

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

        loginPage.clickLogin();
    }

    @Then("User should be able to login successfully")
    public void clickOnLoginButton() {

        assertTrue(homePage.getHomPageTitle().contains("Dashboard"));
    }

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

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

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

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

}

Assertions in JUnit-Jupiter are imported from the below package:-

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

Step 10 – Create a Serenity-Cucumber Runner class

Cucumber runs the feature files via JUnit and needs a dedicated test runner class to actually run the feature files.

import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME;
import org.junit.platform.suite.api.ConfigurationParameter;
import org.junit.platform.suite.api.IncludeEngines;
import org.junit.platform.suite.api.SelectClasspathResource;
import org.junit.platform.suite.api.Suite;

@Suite
@IncludeEngines("cucumber")
@SelectClasspathResource("org.example")
@SelectClasspathResource("/features")
@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "org.example")
public class CucumberTestSuite {

}

Step 11 – Create cucumber.properties file under src/test/resources (optional)

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

cucumber.publish.enabled = true

Step 12 – Create junit-platform.properties in src/test/resources

cucumber.execution.parallel.enabled=true
cucumber.execution.parallel.config.strategy=fixed
cucumber.execution.parallel.config.fixed.parallelism=3
cucumber.plugin=io.cucumber.core.plugin.SerenityReporterParallel

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

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

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

webdriver {
    driver = chrome
}

serenity.browser.maximized = true

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

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

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

serenity.project.name = Parallel Execution of Cucumber Scenarios with Serenity

Step 15 – Run the tests from Command Line

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

mvn clean verify

Below is the test result of the test execution.

Step 16 – Run the tests from CucumberRunner

Right-click on the Ruuner class (CucumberTestSuite) and select Run ‘CucumberTestSuite’. (This is an image of IntelliJ Runner class).

The below image shows that 3 browsers open simultaneously.

Below is the test result of the test execution.

Step 17 – Serenity Report Generation

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

Index.html

serenity-summary.html

If you want to control the number of browsers open in the test, then add the below-mentioned parameters in the junit-platform.properties:

cucumber.execution.parallel.config.fixed.parallelism=2
cucumber.execution.parallel.config.fixed.max-pool-size=2

Here, count=3 is the number of browsers that will open.

Please also remove <useUnlimitedThreads>true</useUnlimitedThreads> from pom.xml.

Note: While .fixed.max-pool-size effectively limits the maximum number of concurrent threads, Cucumber does not guarantee that the number of concurrently executing scenarios will not exceed this. This is from JUnit-Platform documentation.

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

You can see this framework in GitHub.

Serenity BDD Tutorials

HOME

Serenity BDD is an open-source library that aims to make the idea of living documentation a reality.
Serenity BDD helps you write cleaner and more maintainable automated acceptance and regression tests faster. Serenity also uses the test results to produce illustrated, narrative reports that document and describe what your application does and how it works. Serenity tells you not only what tests have been executed, but more importantly, what requirements have been tested

Basics of Serenity

Chapter 1 How to run Serenity BDD tests in Chrome Browser
Chapter 2 How to run Serenity BDD tests in Edge Browser
Chapter 3 Testing of Web Application using Serenity with JUnit4
Chapter 4 Integration of Serenity with JUnit5
Chapter 5 Manual Tests in Serenity with JUnit5
Chapter 6 Integration of Serenity with Rest Assured
Chapter 7 Data Driven Tests in Serenity with JUnit
Chapter 8 Data Driven Tests using CSV file in Serenity
Chapter 9 Implicit Wait in Serenity
Chapter 10 Explicit Wait in Serenity
Chapter 11 Fluent Wait in Serenity – NEW
Chapter 12 Serenity Testing on Different Browsers – NEW

Serenity with Cucumber

Chapter 1 Serenity BDD with Cucumber and JUnit4 for Web Application
Chapter 2 Serenity BDD with Cucumber for SpringBoot Application
Chapter 3 Serenity BDD with Cucumber and Rest Assured
Chapter 4 Testing of SpringBoot REST Application using Rest Assured for GET Method
Chapter 5 Serenity Report for Web Application with Cucumber6 and Junit
Chapter 6 Integration of Serenity with Cucumber and JUnit5
 Chapter 7 Testing of SpringBoot Application with Serenity BDD, Cucumber and JUnit5 – NEW

Serenity Reports

Chapter 1 Serenity Report for Web Application with Cucumber6 and Junit
Chapter 2 Serenity Emailable HTML Report
Chapter 3 Serenity Emailable Report in Gradle
Chapter 4 How to report Manual Tests in Serenity Report
Chapter 5 How to attach Test Evidence to Manual Tests in Serenity Report
Chapter 6 How to manage screenshots in Serenity Report
Chapter 7 How to generate Serenity Report in customized path

Serenity with Gradle

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

Serenity with CI/CD

Chapter 1 Serenity with Jenkins
Chapter 2 How to create Jenkins pipeline for Serenity tests
Chapter 3 How to run Serenity tests with GitHub Actions
Chapter 4 Run Serenity Tests in GitLab CI/CD

Parallel Testing

Chapter 1 Parallel Execution of Cucumber with Serenity and JUnit5

Integration Testing of SpringBoot Application with Serenity BDD, Cucumber and JUnit4

HOME

Relationship between SpringBoot, Serenity BDD, Cucumber and Rest Assured

Implementation Steps

  1. Create a source folder – src/test/resources to create test scenarios in the Feature file
  2. Add SpringBoot, Serenity, Cucumber, and JUnit4 dependencies to the project
  3. Create a feature file under src/test/resources
  4. Create the StepDefinition and Helper classes.
  5. Create a Serenity Runner class in the src/test/java directory
  6. Run the tests from JUnit
  7. Run the tests from Command Line
  8. Serenity Report Generation
  9. Cucumber Report Generation

Step 1 – Create a source folder – src/test/resources

Right-click on the test directory and select New->Directory and select resources (Maven Source Directories). Create a source folder – src/test/resources to create test scenarios in the Feature file

Step 2 – Add SpringBoot, Serenity, Cucumber, and JUnit4 dependencies to the project

We have added SpringBootTest, Serenity, Cucumber, JUnit4, and JUnit Vintage.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.1.0-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.example</groupId>
    <artifactId>Springboot_Serenity_Demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Springboot_Serenity_Demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>11</java.version>
        <serenity.version>3.6.12</serenity.version>
        <maven.surefire.plugin.version>3.0.0-M9</maven.surefire.plugin.version>
        <maven.failsafe.plugin.version>3.0.0-M9</maven.failsafe.plugin.version>
        <parallel.tests></parallel.tests>
        <maven.compiler.plugin.plugin>3.10.1</maven.compiler.plugin.plugin>
        <maven.compiler.source.version>11</maven.compiler.source.version>
        <maven.compiler.target.version>11</maven.compiler.target.version>
        <tags></tags>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
        </dependency>

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

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

		<!-- Serenity With Rest Assured -->
        <dependency>
            <groupId>net.serenity-bdd</groupId>
            <artifactId>serenity-rest-assured</artifactId>
            <version>${serenity.version}</version>
            <scope>test</scope>
        </dependency>

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

        <!-- Serenity With Spring -->
        <dependency>
            <groupId>net.serenity-bdd</groupId>
            <artifactId>serenity-spring</artifactId>
            <version>${serenity.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.junit.vintage</groupId>
            <artifactId>junit-vintage-engine</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>${maven.surefire.plugin.version}</version>
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>${maven.failsafe.plugin.version}</version>
                <configuration>
                    <includes>
                        <include>SpringRunnerTests.java</include>
                        <include>**/Test*.java</include>
                    </includes>
                    <parallel>methods</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.plugin}</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>
                <configuration>
                    <tags>${tags}</tags>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>net.serenity-bdd</groupId>
                        <artifactId>serenity-core</artifactId>
                        <version>${serenity.version}</version>
                    </dependency>
                </dependencies>
                <executions>
                    <execution>
                        <id>serenity-reports</id>
                        <phase>post-integration-test</phase>
                        <goals>
                            <goal>aggregate</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <releases>
                <enabled>false</enabled>
            </releases>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
        <pluginRepository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <releases>
                <enabled>false</enabled>
            </releases>
        </pluginRepository>
    </pluginRepositories>

</project>

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

Below is an example of a feature file which shows a sample test scenario.

Feature: SpringBoot Request
   
@ReceiveCorrectResponse

   Scenario Outline: Send a valid Request to get correct response
    Given I send a request to the URL "<url>"
    Then the response will return "<response>"

   Examples:
   | url             | response                   |
   | /               | Hello World, Spring Boot!  |
   | /qaautomation   | Hello QA Automation!       |

The test class mentioned below (AbstractRestAssuredHelper) contains integration tests for the spring boot rest controller mentioned. This test class:

  • uses @SpringBootTest annotation which loads the actual application context.
  • uses WebEnvironment.RANDOM_PORT to create and run the application at some random server port.
  • @LocalServerPort gets the reference of the port where the server has started. It helps in building the actual request URIs to mimic real client interactions.

Step 4 – Create the StepDefinition and Helper classes

Below is the code of the StepDefinition and Helper class. These classes are created in the src/test/java directory.

AbstractRestAssuredHelper

import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalServerPort;
import io.restassured.RestAssured;
import io.restassured.specification.RequestSpecification;
import net.serenitybdd.rest.SerenityRest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public abstract class AbstractRestAssuredHelper {
     private final static String BASE_URI = "http://localhost";
 
     @LocalServerPort
     private int port;
 
     protected void configureRestAssured() {
           RestAssured.baseURI = BASE_URI;
           RestAssured.port = port;    
 
     }

     protected RequestSpecification getAnonymousRequest() {
           configureRestAssured();
           return SerenityRest.given();
     }
}

This class sends the request and receives a response after performing the GET operation. Here, the validation of the response also takes place by asserting the expected and actual response

To use Rest-assured, Serenity provides the class SerenityRest

import org.junit.Assert;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.restassured.response.Response;
import net.serenitybdd.rest.SerenityRest;
import net.thucydides.core.annotations.Steps;

public class SpringBootDemoDefinitions {

	@Steps
    AbstractRestAssuredHelper helper;
    private Response response;

    @Given("I send a request to the URL {string}")
    public void iSendARequest(String endpoint) throws Exception  {
         response = helper.getAnonymousRequest().contentType("application/json")
                    .header("Content-Type", "application/json").when().get(endpoint);
    }

    @Then("the response will return {string}")
    public void extractResponse(String Expected ) {
          SerenityRest.restAssuredThat(response -> response.statusCode(200));
          String Actual = response.asString();    
          Assert.assertEquals(Expected, Actual); 
    }
}

Step 5 – Create a Serenity Runner class in the src/test/java directory

We cannot run a Feature file on its own in cucumber-based framework. We need to create a Java class that will run the Feature File. It is the starting point for JUnit to start executing the tests. TestRunner class is created under src/ test/javaWhen 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 can be found.

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

@RunWith(CucumberWithSerenity.class)
@CucumberOptions(features = "src/test/resources", tags = "", glue = "com.example.Springboot_Serenity_Demo.definitions", publish = true)

public class SpringRunnerTests {

}

Step 6 – Run the tests from JUnit

You can run the tests from SpringRunnerTests class. Right-click on the class and select Run ‘SpringRunnerTests’.

Step 7 – Run the tests from Command Line

Run the tests from the command line by using the below command

mvn clean verify

The output of the above program is

The test execution status is shown below:

Step 8 – Serenity Report Generation

By default, the test report generated by Serenity is placed under target/site/serenity/index.html. Below is the sample Serenity Report.

Go to the Test Results tab and we can see all the test scenarios.

Step 9 – Cucumber Report Generation

Cucumber Report can be generated by adding publish=true in SpringRunnerTests as shown in the above example. Click on the link provided in the execution status.

Cucumber Report

The next tutorial explains about the Testing of SpringBoot REST Application using Serenity BDD and Rest Assured for GET Method.

The complete code can be found in GitHub.

How to create JUnit Report in Jenkins

Last Updated On

HOME

In this tutorial, we show you how to generate JUnit Report Using Jenkins. In the previous tutorial, we generated a TestNG Report using Jenkins.

Table of Contents

  1. Prerequisite
  2. Implementation Steps
    1. Start the Jenkins server
    2. Create a new FreeStyle project
    3. Build Steps
    4. Provide the full path to pom.xml
    5. Select “Publish JUnit test result report” from “Post Build Actions”
    6. Execute the tests
    7. View the JUnit Report

Prerequisite

3. To generate JUnit Report, please refer to this tutorial to get the code – How to generate JUnit4 Report.

4. To generate a JUnit Report in Jenkins, we need to download the JUnit Plugin. Please refer to this tutorial to install the plugin – How to install Plugins in Jenkins

Implementation Steps

Step 1: Start the Jenkins server

Start the Jenkins server open the browser and navigate to the below endpoint

http://localhost:8080/

Step 2: Create a new FreeStyle project

  1. Give the Name of the project – JUnitReport_Demo
  2. Click on the Freestyle project. 
  3. Click on the OK

In the General section, enter the project description in the Description box.

Select a custom workspace and provide the full path of the project.

Select Source Code Management as None if the project is locally present on the machine

Step 3: Build Steps

In the Build Steps section, select Invoke top-level Maven targets.

The Build Steps window will extend. Mention the below details:-

Maven Version – MAVEN_HOME

Goals – clean test

Click on the Advanced button.

Step 4: Provide the full path to pom.xml

Specify the full path to pom.xml in POM.

Step 5: Select “Publish JUnit test result report” from “Post Build Actions”

Scroll down to “Post Build Actions” and click on the “Add Post Build Actions” drop-down list. Select Publish JUnit test result report“. 

Enter the Result Path as “**/target/surefire-reports/*.xml”.

Click on the Apply and Save buttons.

We have created a new Maven project JUnitReport_Demo” with the configuration to run the Selenium with JUnit Tests and also to generate JUnit Report after execution using Jenkins.

Step 6: Execute the tests

Let’s execute it now by clicking on the “Build Now” button. 

Right-click on Build Number (here in my case it is #2).

Click on Console Output to see the result.

Step 7: View the JUnit Report

Once the execution is completed, we could see a link to view the “Test Report“.

Below is the summary of the Test Execution.

This way, we could generate JUnit Report using Jenkins.

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

Additional Tutorials

Jenkins GitLab Integration
How to create Jenkins pipeline for Selenium tests
How to create Jenkins pipeline for Serenity tests
How to generate TestNG Report in Jenkins
How to create Jenkins pipeline for Extent Report
How to run parameterized Selenium tests in Jenkins

How to test PATCH Request using Rest Assured

HOME

In the last tutorial, I explained How to test POST Request using Rest Assured. In this tutorial, I will automate a PATCH Request using Rest Assured. I will verify the status code, line of Status, and content of the Response.

To set up a basic Rest Assured Maven Project, click here and Gradle project, click here.

<dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.1</version>
      <scope>test</scope>
</dependency>
  
<dependency>
      <groupId>io.rest-assured</groupId>
      <artifactId>rest-assured</artifactId>
      <version>5.3.2</version>
      <scope>test</scope>
</dependency>

What is the PATCH Method?

The HTTP PATCH request method applies partial modifications to a resource

Below are the steps to test a PATCH Request using Rest Assured:

The steps to test the PATCH request are similar to the PUT request.

Below is the example for the test to PATCH method. (Non BDD)

import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import io.restassured.response.Response;
import io.restassured.response.ValidatableResponse;
import io.restassured.specification.RequestSpecification;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.equalTo;

public class Patch_NonBDDDemo {

    RequestSpecification requestSpecification;
    Response response;
    ValidatableResponse validatableResponse;

    @Test
    public void updateUser() {

        String jsonString = "{\"name\": \"William\"}";

        RestAssured.baseURI = "https://reqres.in/api/users/2";

        // Create a request specification
        requestSpecification = RestAssured.given();

        // Setting content type to specify format in which request payload will be sent.
        requestSpecification.contentType(ContentType.JSON);

        // Adding body as string
        requestSpecification.body(jsonString);

        // Calling PATCH method
        response = requestSpecification.patch();

        // Let's print response body.
        String responseString = response.prettyPrint();

        /*
         * To perform validation on response, we need to get ValidatableResponse type of
         * response
         */
        validatableResponse = response.then();

        // Get status code
        validatableResponse.statusCode(200);

        // It will check if status line is as expected
        validatableResponse.statusLine("HTTP/1.1 200 OK");

        // Check response - name attribute
        validatableResponse.body("name", equalTo("William"));

    }
}

Test implemented in BDD Format

import io.restassured.http.ContentType;
import io.restassured.response.Response;
import io.restassured.response.ValidatableResponse;
import io.restassured.specification.RequestSpecification;
import org.junit.Test;
import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.equalTo;

public class Patch_BDDDemo {

    RequestSpecification requestSpecification;
    Response response;
    ValidatableResponse validatableResponse;

    @Test
    public void updateUser() {

       String jsonString = "{\"name\": \"William\"}";

        // Update name
        validatableResponse = given()
                .baseUri("https://reqres.in/api/users/2")
                .contentType(ContentType.JSON)
                .body(jsonString)
                .when()
                .patch()
                .then()
                .assertThat().statusCode(200)
                .body("name", equalTo("William"));

        System.out.println("Response :" + validatableResponse.extract().asPrettyString());

    }

}

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

How to test DELETE in Rest Assured

HOME

In the last tutorial, I explained How to test PUT Request using Rest Assured. In this tutorial, I will automate a DELETE Request using Rest Assured. I will verify the status code, line of Status, and content of the Response.

To set up a basic Rest Assured Maven Project, click here and Gradle project, click here.

<dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.1</version>
      <scope>test</scope>
</dependency>
  
<dependency>
      <groupId>io.rest-assured</groupId>
      <artifactId>rest-assured</artifactId>
      <version>5.3.2</version>
      <scope>test</scope>
</dependency>

What is the DELETE Method?

An HTTP DELETE method is used to delete an existing resource from the collection of resources. The DELETE method requests the origin server to delete the resource identified by the Request-URI. On successful deletion of a resource, it returns  200 (OK) and 204 (No Content) status codes. It may return as 202 (Accepted) status code if the request is queued. To learn more about Rest API, please click here.

Below are the steps to test a DELETE Request using Rest Assured:

The steps to test the DELETE request are similar to any API request like GET, POST, or PUT. To know about the steps and various imports used in the below example in detail, please refer to the tutorial for POST Request.

Let’s see the existing details of an Employee ID 3 using Postman:

Let’s write DELETE request in REST Assured in Non BDD Format for id 3:-

import io.restassured.RestAssured;
import io.restassured.response.Response;
import io.restassured.response.ValidatableResponse;
import io.restassured.specification.RequestSpecification;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.equalTo;

public class Delete_NonBddDemo {

    RequestSpecification requestSpecification;
    Response response;
    ValidatableResponse validatableResponse;

    @Test
    public void deleteUser() {

        RestAssured.baseURI = "https://dummy.restapiexample.com/api";

        // Create a request specification
        requestSpecification = RestAssured.given();

        // Calling DELETE method
        response = requestSpecification.delete("/v1/delete/3");

        // Let's print response body.
        String resString = response.prettyPrint();

        /*
         * To perform validation on response, we need to get ValidatableResponse type of
         * response
         */
        validatableResponse = response.then();

        // Get status code
        validatableResponse.statusCode(200);

        // It will check if status line is as expected
        validatableResponse.statusLine("HTTP/1.1 200 OK");

        // Check response - message attribute
        validatableResponse.body("message", equalTo("Successfully! Record has been deleted"));

    }
}

Let’s write DELETE request in REST Assured in BDD Format:

import io.restassured.http.ContentType;
import io.restassured.response.ValidatableResponse;
import org.junit.Test;
import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.equalTo;

public class Delete_BDDDemo {

    ValidatableResponse validatableResponse;

    @Test
    public void deleteUser() {
        
        validatableResponse = given()
                .baseUri("https://dummy.restapiexample.com/api/v1/delete/3")
                .contentType(ContentType.JSON)
                .when()
                .delete()
                .then()
                .assertThat().statusCode(200)
                .body("message", equalTo("Successfully! Record has been deleted"));

        System.out.println("Response :" + validatableResponse.extract().asPrettyString());

    }

}

.baseUri("https://dummy.restapiexample.com/api/v1/delete/3")
  .contentType(ContentType.JSON)
assertThat().statusCode(200)
.body("message", equalTo("Successfully! Record has been deleted"));

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

How to test PUT Request using Rest Assured

HOME

In the last tutorial, I explained How to test POST Request using Rest Assured. In this tutorial, I will automate a PUT Request using Rest Assured. I will verify the status code, line of Status, and content of the Response.

To set up a basic Rest Assured Maven Project, click here and Gradle project, click here.

<dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.1</version>
      <scope>test</scope>
</dependency>
  
<dependency>
      <groupId>io.rest-assured</groupId>
      <artifactId>rest-assured</artifactId>
      <version>5.3.2</version>
      <scope>test</scope>
</dependency>

What is the PUT Method?

The HTTP PUT API is primarily used to update existing resources. If the resource does not exist, then API may decide to create a new resource or not (Depending on API development). If a new resource has been created by the PUT API, the origin server MUST inform the user agent via the HTTP response code 201 (Created) response, and if an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate successful completion of the request. To learn more about Rest API, please click here.

Below are the steps to test a PUT Request using Rest Assured:

The steps to test the PUT request are similar to the POST request. The only difference is that in POST we send a request to create a new resource, whereas here we have a resource and I will update the detail of the already existing resource. To know about the steps and various imports used in the below example, please refer to the tutorial for POST Request.

Below is the response received for Employee with id 2.

I want to change the employee_salary to 99999. Below is the example for the test to update employee_salary.

import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import io.restassured.response.Response;
import io.restassured.response.ValidatableResponse;
import io.restassured.specification.RequestSpecification;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.equalTo;

public class PUT_NonBDDDemo {

    RequestSpecification requestSpecification;
    Response response;
    ValidatableResponse validatableResponse;

    @Test
    public void updateUser() {

        String jsonString = "{\"id\": 2,\r\n"
                + "        \"employee_name\": \"Garrett Winters\",\r\n"
                + "        \"employee_salary\": 99999,\r\n"
                + "        \"employee_age\": 63,\r\n"
                + "        \"profile_image\": \"\"}";

        RestAssured.baseURI = "https://dummy.restapiexample.com/api/v1/update/2";

        // Create a request specification
        requestSpecification = RestAssured.given();

        // Setting content type to specify format in which request payload will be sent.
        requestSpecification.contentType(ContentType.JSON);

        // Adding body as string
        requestSpecification.body(jsonString);

        // Calling PUT method
        response = requestSpecification.put();

        // Let's print response body.
        String responseString = response.prettyPrint();

        /*
         * To perform validation on response, we need to get ValidatableResponse type of
         * response
         */
        validatableResponse = response.then();

        // Get status code
        validatableResponse.statusCode(200);

        // It will check if status line is as expected
        validatableResponse.statusLine("HTTP/1.1 200 OK");

        // Check response - name attribute
        validatableResponse.body("data.employee_salary", equalTo(99999));

        // Check response - message attribute
        validatableResponse.body("message", equalTo("Successfully! Record has been updated."));

    }
}

Now, let us convert the same test into BDD format. In the below example, in the first part, we have retrieved the details of the employee with ID 2, and in the second part, we have updated the value of employee_salary to 99999.

import io.restassured.http.ContentType;
import io.restassured.response.Response;
import io.restassured.response.ValidatableResponse;
import io.restassured.specification.RequestSpecification;
import org.junit.Test;
import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.equalTo;

public class PUT_BDDDemo {

    RequestSpecification requestSpecification;
    Response response;
    ValidatableResponse validatableResponse, validatableResponse1;

    @Test
    public void updateUser() {

        // To get the detail of employee with id 2
        validatableResponse = given()
                .baseUri("https://dummy.restapiexample.com/api/v1/employee/2")
                .contentType(ContentType.JSON)
                .when()
                .get()
                .then()
                .assertThat().statusCode(200);

        System.out.println("Response1 :" + validatableResponse.extract().asPrettyString());

        String jsonString = "{\"id\": 2,\r\n"
                + "        \"employee_name\": \"Garrett Winters\",\r\n"
                + "        \"employee_salary\": 99999,\r\n"
                + "        \"employee_age\": 63,\r\n"
                + "        \"profile_image\": \"\"}";

        // Update employee_salary
        validatableResponse1 = given()
                .baseUri("https://dummy.restapiexample.com/api/v1/update/2")
                .contentType(ContentType.JSON)
                .body(jsonString)
                .when()
                .put()
                .then()
                .assertThat().statusCode(200)
                .body("data.employee_salary", equalTo(99999))
                .body("message", equalTo("Successfully! Record has been updated."));

        System.out.println("Response2 :" + validatableResponse1.extract().asPrettyString());

    }

}

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

How to test SOAP Services using Rest Assured

HOME

In this tutorial, I will test a SOAP Service using Rest Assured. I will verify the status code, line of Status, and content of the Response. To set up a basic Rest Assured Maven Project, click here and Gradle project, click here.

Add the below-mentioned dependencies to the pom.xml.

<dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.1</version>
      <scope>test</scope>
</dependency>
 
<dependency>
      <groupId>io.rest-assured</groupId>
      <artifactId>rest-assured</artifactId>
      <version>5.3.2</version>
      <scope>test</scope>
</dependency>

What is the SOAP WebService?

SOAP is an XML-based protocol for accessing web services over HTTP. It has some specifications that could be used across all applications.

Implementation Steps:

Step 2 – Specify the base URL to the RESTful web service using the RestAssured class.

RestAssured.baseURI = "http://www.dneonline.com";

Step 3  The response to a request made by REST Assured.

  Response response = given()

Response is imported from package:

import io.restassured.response.Response;

Step 4 – Set the content type to specify the format in which the request payload will be sent to the server. Here, the Content-Type is “text/xml; charset=utf-8”.

 .header("Content-Type", "text/xml; charset=utf-8")

Step 5 Pass Request Body.

   .body(requestBody)
 requestBody = new File(getClass().getClassLoader().getResource("Number.xml").getFile());

Step 6 – Send the POST request to the server and receive the response of the request made by REST Assured. This response contains every detail returned by hitting request i.e. response body, response headers, status code, status lines, cookies, etc. The response is imported from package:

import io.restassured.response.Response;

Step 7 – To validate a response like status code or value, we have used the below code

 Assert.assertEquals(200, response.statusCode());
Assert.assertEquals(13, result);

PrettyPrint() – It prints the response body if possible and returns it as a string. Pretty printing is possible for content types JSON, XML, and HTML.

System.out.println(response.prettyPrint());

Below is an example of testing a SOAP Web Service request using the Rest Assured.

import io.restassured.response.Response;
import org.junit.Assert;
import org.junit.Test;
import java.io.File;
import static io.restassured.RestAssured.given;

public class RestAssured_SOAPDemo {

    File requestBody;
    Response response;

    @Test
    public void test() {

        requestBody = new File(getClass().getClassLoader().getResource("Number.xml").getFile());
        response = given()
                .baseUri("http://www.dneonline.com")
                .basePath("/calculator.asmx")
                .header("Content-Type", "text/xml; charset=utf-8")
                .body(requestBody)
                .post();

        System.out.println(response.prettyPrint());

        var xPathResult = response.xmlPath().get("//SubtractResult/text()");
        var result = Integer.parseInt(String.valueOf(xPathResult));

        System.out.println("xPathResult :" + xPathResult);
        System.out.println("result :" + result);

        Assert.assertEquals(200, response.statusCode());
        Assert.assertEquals(13, result);
    }

}

The below image shows the test result of the above test.

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

How to test POST Request using Rest Assured

HOME

In the last tutorial, I explained How to test GET Request using Rest Assured. In this tutorial, I will automate a POST Request using Rest Assured. I will verify the status code, line of Status, and content of the Response. To set up a basic Rest Assured Maven Project, click here and Gradle project, click here.

Add the below-mentioned dependencies to the pom.xml. The latest dependency can be downloaded from here.

<dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.2</version>
      <scope>test</scope>
</dependency>
 
<dependency>
      <groupId>io.rest-assured</groupId>
      <artifactId>rest-assured</artifactId>
      <version>5.5.1</version>
      <scope>test</scope>
</dependency>

What is the POST Method?

An HTTP POST method is used to create a new resource in the collection of resources. The request body is passed as a JSON/XML or in a different format. If a resource is created successfully by the endpoint or server, it returns a status code 201(Created). It also provides a Location header with a link to the newly-created resource with the 201 HTTP status. It may return 200 (OK) and 204 (No Content) status code as well, based on how the API is developed.

POST is neither safe nor idempotent. It is therefore recommended for non-idempotent resource requests. Making two identical POST requests will most result in two resources containing the same information.

Below are the steps to test a POST Request using Rest Assured:

Step 1 Specify the base URL to the RESTful web service using the RestAssured class.

RestAssured.baseURI = "https://dummy.restapiexample.com/api/v1/create";

Step 2  Every Request in the Rest-Assured library is represented by an interface called RequestSpecification. This interface allows modifying the request, like adding headers or adding authentication details. Use the RestAssured class to generate a RequestSpecification.

requestSpecification = RestAssured.given();

RequestSpecification is imported from package:

import io.restassured.specification.RequestSpecification;

Step 3 – Set the content type. This step specifies the format in which the request payload will be sent to the server. Here, the Content-Type is JSON.

requestSpecification.contentType(ContentType.JSON);

contentType is imported from restassured.http package:

import io.restassured.http.ContentType;

Step 4 Pass Request Body as String.

requestSpecification.body(jsonString);

Step 5 – Send the POST request to the server. Then receive the response of the request made by REST Assured. This response contains every detail returned by hitting request i.e. response body, response headers, status code, status lines, cookies, etc. The response is imported from package:

import io.restassured.response.Response;

Step 6 To validate a response like status code or value, we need to get the reference of type ValidatableResponse

ValidatableResponse is an interface. A validatable response to a request made by, REST Assured. ValidatableResponse is imported from package:

import io.restassured.response.ValidatableResponse;

PrettyPrint() – It prints the response body if possible and returns it as a string. Pretty printing is possible for content-types JSON, XML, and HTML.

Below is the example of testing a POST request in Non-BDD format. I have used ValidatableResponse for the assertion of status. It is also used for the status line and body of the Response.

import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import io.restassured.response.Response;
import io.restassured.response.ValidatableResponse;
import io.restassured.specification.RequestSpecification;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.equalTo;

public class POST_NonBDDDemo {

    RequestSpecification requestSpecification;
    Response response;
    ValidatableResponse validatableResponse;

    @Test
    public void verifyStatusCode() {

        String jsonString = "{\"name\":\"newapitest\",\"salary\":\"4000\",\"age\":\"29\"}";

        RestAssured.baseURI = "https://dummy.restapiexample.com/api/v1/create";

        // Create a request specification
        requestSpecification = RestAssured.given();

        // Setting content type to specify format in which request payload will be sent.
        requestSpecification.contentType(ContentType.JSON);

        // Adding body as string
        requestSpecification.body(jsonString);

        // Calling POST method
        response = requestSpecification.post();

        // Let's print response body.
        String responseString = response.prettyPrint();

        /*
         * To perform validation on response, we need to get ValidatableResponse type of
         * response
         */
        validatableResponse = response.then();

        // Check status code
        validatableResponse.statusCode(200);

        // It will check if status line is as expected
        validatableResponse.statusLine("HTTP/1.1 200 OK");

        // Check response body - name attribute
        validatableResponse.body("data.name", equalTo("newapitest"));

        // Check response body - message attribute
        validatableResponse.body("message", equalTo("Successfully! Record has been added."));

    }
}

The below image shows the test result of the above test.

Test implemented in BDD Format

import static org.hamcrest.Matchers.equalTo;

2. given is a static import from package:

import static io.restassured.RestAssured.given;

Below is an example of a BDD Test.

import io.restassured.http.ContentType;
import io.restassured.response.ValidatableResponse;
import org.junit.Test;
import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.equalTo;

public class POST_BDDDemo {
    
    ValidatableResponse validatableResponse;

    @Test
    public void createUser() {

        String json = "{\"name\":\"apitest\",\"salary\":\"5000\",\"age\":\"30\"}";

        // GIVEN
        validatableResponse = given()
                .baseUri("https://dummy.restapiexample.com/api")
                .contentType(ContentType.JSON)
                .body(json)

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

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

        System.out.println("Response :" + validatableResponse.extract().asPrettyString());
    }

}

The below image shows the test result of the above test.

String json = "{\"name\":\"apitest\",\"salary\":\"5000\",\"age\":\"30\"}";

.baseUri("https://dummy.restapiexample.com/api")
.contentType(ContentType.JSON)
.body(json)

".assertThat().statusCode(200)"
.body("data.name", equalTo("apitest"))
.body("message", equalTo("Successfully! Record has been added."))

The above tests can be used in both Maven and Gradle projects.

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

How to test GET Request using Rest Assured

HOME

In the last tutorial, I explained the Setup of the REST Assured Maven Project In Eclipse IDE. In this tutorial, I will automate a GET Request. I will verify the status code, line of Status, and content of the Response.

RestAssured is a class that consists of many static fields and methods. It supports POST, GET, PUT, DELETE, HEAD, PATCH, and OPTIONS requests and verifies the response to these requests.

 <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.2</version>
      <scope>test</scope>
</dependency>

<dependency>
      <groupId>io.rest-assured</groupId>
      <artifactId>rest-assured</artifactId>
      <version>5.5.5</version>
      <scope>test</scope>
</dependency>

Below are the steps to test a GET Request using Rest Assured:

Step 1 Specify the base URL to the RESTful web service using the RestAssured class.

RestAssured.baseURI = "http://dummy.restapiexample.com/api/v1/employees";

Step 2 Every Request in the Rest-Assured library is represented by an interface called RequestSpecification. This interface allows modification of the request, like adding headers or adding authentication details.

requestSpecification = RestAssured.given();

RequestSpecification is imported from the package:

import io.restassured.specification.RequestSpecification;

Step 3 Send the request to the server and receive the response to the request made by REST Assured. This response contains every detail returned by hitting request i.e. response body, response headers, status code, status lines, cookies, etc.

response = requestSpecification.get();

The response is imported from package:

import io.restassured.response.Response;

Step 4 To validate a response like status code or value, we need to acquire a reference. This reference should be of type ValidatableResponse. ValidatableResponse is an interface. A validatable response to a request made by, REST Assured. ValidatableResponse is imported from the package:

import io.restassured.response.ValidatableResponse;

PrettyPrint() It prints the response body if possible and returns it as a string. Pretty printing is possible for content-types JSON, XML, and HTML.

Below is an example of creating a test in Non-BDD format. I have used ValidatableResponse for the assertion of the status. It is also used for the status line of the Response.

import io.restassured.RestAssured;
import io.restassured.response.Response;
import io.restassured.response.ValidatableResponse;
import io.restassured.specification.RequestSpecification;
import org.junit.Test;

public class Get_NonBDDDemo {
    RequestSpecification requestSpecification;
    Response response;
    ValidatableResponse validatableResponse;

    @Test
    public void verifyStatusCode() {

        RestAssured.baseURI = "http://dummy.restapiexample.com/api/v1/employees";

        // Create a request specification
        requestSpecification = RestAssured.given();

        // Calling GET method
        response = requestSpecification.get();

        // Let's print response body.
        String resString = response.prettyPrint();
        System.out.println("Response Details : " + resString);

        /*
         * To perform validation on response, we need to get ValidatableResponse type of
         * response
         */
        validatableResponse = response.then();

        // Get status code
        validatableResponse.statusCode(200);

        // Check status line is as expected
        validatableResponse.statusLine("HTTP/1.1 200 OK");

    }
}

If you don’t want to use ValidatableResponse for the assertion, you can use Response from io.restassured .response to get the status code and status line, which are asserted using JUnit.Assert.

import io.restassured.RestAssured;
import io.restassured.response.Response;
import io.restassured.response.ValidatableResponse;
import io.restassured.specification.RequestSpecification;
import org.junit.Assert;
import org.junit.Test;

public class Get_NonBDDResponseDemo {
    RequestSpecification requestSpecification;
    Response response;

    @Test
    public void verifyStatusCode() {

        RestAssured.baseURI = "http://dummy.restapiexample.com/api/v1/employees";

        // Create a request specification
        requestSpecification = RestAssured.given();

        // Calling GET method
        response = requestSpecification.get();

        // Let's print response body.
        String resString = response.prettyPrint();
        System.out.println("Response Details : " + resString);

        // Get status line
        String statusLine = response.getStatusLine();
        Assert.assertEquals(statusLine, "HTTP/1.1 200 OK");

        // Get status code
        int statusCode = response.getStatusCode();
        Assert.assertEquals(statusCode, 200);

    }
}

The output of the above program is

Below is the test implemented in BDD Format. In this test, I am asserting the data of Employee of Id 2. I have validated the name of the employee as well as the response message.

1. equalTo is used for assertion, and is imported from a static hamcrest package:

import static org.hamcrest.Matchers.equalTo;

2. given is a static import from package:

import static io.restassured.RestAssured.given;

import org.junit.Test;
import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.equalTo;

public class Get_BDDDemo {

    @Test
    public void verifyUser() {

        // Given
        given()

                // When
                .when()
                .get("http://dummy.restapiexample.com/api/v1/employee/2")

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

                // To verify booking id at index 3
                .body("data.employee_name", equalTo("Garrett Winters"))
                .body("message", equalTo("Successfully! Record has been fetched."));
    }

}

    given
    
    .when()
    .get("http://dummy.restapiexample.com/api/v1/employee/2")
    
    .then()
    .statusCode(200)
    .statusLine("HTTP/1.1 200 OK")
    
    .body("data.employee_name", equalTo("Garrett Winters"))
    .body("message", equalTo("Successfully! Record has been fetched."));
    

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