How to rerun failed tests in Cucumber

Last Updated On

HOME

The previous tutorial explained the Integration of Cucumber with Selenium and TestNG. Sometimes, inconsistent test results are common as a result of an unstable environment like network issue or Database down and soon. A few tests may fail for no obvious reason and then rerun successfully. We are sometimes required to run only failed test cases after bug fixes to verify fixes quickly. We will learn how to rerun failed test cases in the Cucumber with TestNG project in this post.

Cucumber provides a rerun plugin option in the Runner class. This option generates a file. The file contains information about the failed tests.

The Cucumber Framework with Selenium and TestNG can be found here. Refer to this tutorial to setup the project – Integration of Cucumber with Selenium and TestNG.

Now, let us add a rerun plugin to the Cucumber Runner class. Here, we are creating a failedrerun.txt file that contains the information about the failed test. This file will be created under the target folder.

import io.cucumber.testng.AbstractTestNGCucumberTests;
import io.cucumber.testng.CucumberOptions;

@CucumberOptions(tags = "", features = "src/test/resources/features/LoginPage.feature",
        glue = "com.example.definitions",
        plugin =  {
        "pretty",
        "rerun:target/rerun.txt" // Saves paths of failed scenarios
    }
)
public class RunnerTests extends AbstractTestNGCucumberTests {
}

Create a Second Runner Class

The next step is to run failed test scenarios existing in the text file. We need to create a class similar to our runner class. This class will contain the location of the file that we want to execute. It will rerun our failed scenarios. In the ‘features’ variable, you need to mention the failedrerun.txt file, and don’t forget that you must mention the ‘@’ symbol before the file path.

import io.cucumber.testng.AbstractTestNGCucumberTests;
import io.cucumber.testng.CucumberOptions;

@CucumberOptions(tags = "",
        features = "@target/rerun.txt",
        glue = "com.example.definitions",
        plugin =  {
                "pretty"
        }
)

public class RunnerTestsFailed extends AbstractTestNGCucumberTests {
}

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Suite">
    <test  name="Cucumber with TestNG Test">
        <classes>
            <class name="com.example.runner.RunnerTests"/>
            <class name="com.example.runner.RunnerTestsFailed"/>
        </classes>
    </test> <!-- Test -->
</suite> <!-- Suite -->

Run the tests using the below-mentioned command

mvn clean test

After running the tests from the command line, first, all the tests will be executed. If any test fails, a failedrerun.txt file will be generated that includes the details about the failed tests.

In the below screenshot, we can see that a scenario starting at line 25 has failed.

The first round of execution ends. Then, Cucumber Runner goes to the second runner. It runs the failed tests that are mentioned in failedrerun.txt.

We can see that 2 separate reports are generated here.

The first Cucumber Report shows that out of 5 tests, 1 test failed.

The second Cucumber Report shows that the one failed test is rerun again, and it again failed.

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

Hooks in Cucumber
Data Driven Testing using Scenario Outline in Cucumber
Integration Testing of Springboot with Cucumber and JUnit4
Background in Cucumber
Allure Report with Cucumber5, Selenium and TestNG

Rest API Test in Cucumber and JUnit4

HOME

Cucumber is not an API automation tool, but it works well with other API automation tools.

There are 2 most commonly used Automation Tools for JVM to test API – Rest-Assured and Karate. In this tutorial, I will use RestAssured with Cucumber and JUnit4 for API Testing.

What is Rest Assured?

REST Assured is a Java library that provides a domain-specific language (DSL) for writing powerful, maintainable tests for RESTful APIs. REST Assured can be used easily in combination with existing unit testing frameworks, such as JUnit and TestNG. Rest assured, no matter how complex the JSON structures are, Rest Assured has methods to retrieve data from almost every part of the request and response.

What is Cucumber?

Cucumber is one such open-source tool, which supports Behaviour Driven Development(BDD). In simple words, Cucumber can be defined as a testing framework, driven by plain English. It serves as documentation, automated tests, and development aid – all in one.

Each scenario is a set of steps that the Cucumber must complete. Cucumber validates the software’s compliance with the specification and generates a report indicating success or failure for each scenario.

The cucumber must adhere to some basic syntax rules known as Gherkin in order to comprehend the scenarios.

In this tutorial, I will explain creating a framework for the testing of Rest API in Cucumber BDD.

This framework consists of:

  1. Cucumber – 7.18.0
  2. Java 17
  3. JUnit – 4.13.2
  4. Maven – 3.9.6
  5. Rest Assured – 5.4.0
  6. Maven Compiler – 3.13.0

Project Structure

Step 1 – Download and Install Java

Cucumber and Rest-Assured need Java to be installed on the system to run the tests. 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. Click here to know How to install Eclipse.

Step 3 – Setup Maven

To build a test framework, we need to add several dependencies to the project. Click here to know How to install Maven.

Step 4 – Create a new Maven Project

File -> New Project-> Maven-> Maven project-> Next -> Enter Group ID & Artifact ID -> Finish

Click here to know How to create a Maven project

Step 5 – Install the Cucumber Eclipse plugin for the Eclipse project (Eclipse Only)

The Cucumber plugin is an Eclipse plugin that allows eclipse to understand the Gherkin syntax. Cucumber Eclipse Plugin highlights the keywords present in Feature File. To install Cucumber Eclipse Plugin, please refer to this tutorial – How to install Cucumber Eclipse Plugin.

Step 6 – Create source folder src/test/resources

A new Maven Project is created with 2 folders – src/main/java and src/test/java. To create test scenarios, we need a new source folder called – src/test/resources. To create this folder, right-click on your maven project ->select New ->Java and then Source Folder.

Mention the source folder name as src/test/resources and click the Next button. This will create a source folder under your new Maven project as shown in the below image.

Step 7 – Add Rest-Assured and Cucumber dependencies to the project

You should place rest-assured before the JUnit dependency declaration in your pom.xml / build.gradle to make sure that the correct version of Hamcrest is used.
REST Assured includes JsonPath and XmlPath as transitive dependencies.

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <rest.assured.version>5.4.0</rest.assured.version>
    <cucumber.version>7.18.0</cucumber.version>
    <junit.version>4.13.2</junit.version>
    <maven.compiler.plugin.version>3.13.0</maven.compiler.plugin.version>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
  </properties>

  <dependencies>

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

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

    <!-- Cucumber with Java -->
    <dependency>
      <groupId>io.cucumber</groupId>
      <artifactId>cucumber-java</artifactId>
      <version>${cucumber.version}</version>
    </dependency>

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

Step 8 – Add Maven Compiler Plugin

The compiler plugin is used to compile the source code of a Maven project. This plugin has two goals, which are already bound to specific phases of the default lifecycle:

  • compile – compile main source files
  • testCompile – compile test source files
<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>
    </plugins>
  </build>

The complete POM.xml will look like something below:

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

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

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

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <rest.assured.version>5.4.0</rest.assured.version>
    <cucumber.version>7.18.0</cucumber.version>
    <junit.version>4.13.2</junit.version>
    <maven.compiler.plugin.version>3.13.0</maven.compiler.plugin.version>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
  </properties>

  <dependencies>

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

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

    <!-- Cucumber with Java -->
    <dependency>
      <groupId>io.cucumber</groupId>
      <artifactId>cucumber-java</artifactId>
      <version>${cucumber.version}</version>
    </dependency>

    <!-- JUnit4 -->
    <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-compiler-plugin</artifactId>
        <version>${maven.compiler.plugin.version}</version>
        <configuration>
          <source>${maven.compiler.source}</source>
          <target>${maven.compiler.target}</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

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

Create a folder with name features. Now, create the feature file in this folder. The feature file should be saved with extension .feature. This feature file contains the test scenarios created to test the application. The Test Scenarios are written in Gherkins language in the format of Given, When, Then, And, But.

Below is an example of a Test Scenario where we are using the GET method to get the information from the API.

Feature: Validation of get method

  @GetUserDetails
  Scenario Outline: Send a valid Request to get user details

    Given I send a request to the URL to get user details
    Then the response will return status <statusCode> and id <id> and email "<employee_email>" and first name "<employee_firstname>" and last name "<employee_lastname>"

    Examples:
    | statusCode | id  | employee_email          | employee_firstname | employee_lastname |
    | 200        | 2   | janet.weaver@reqres.in  | Janet              | Weaver            |

Step 10 – Create the Step Definition class or Glue Code for the Test Scenario

StepDefinition acts as an intermediate to your runner and feature file. It stores the mapping between each step of the scenario in the Feature file. So when you run the scenario, it will scan the step definition file to check the matched glue or test code.

import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.restassured.http.ContentType;
import io.restassured.response.ValidatableResponse;

import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.equalTo;

public class APIDemoDefinitions {
    private ValidatableResponse validatableResponse;
    private String endpoint = "https://reqres.in/api/users/2";

    @Given("I send a request to the URL to get user details")
    public void sendRequest(){
        validatableResponse = given().contentType(ContentType.JSON)
                .when().get(endpoint).then();

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

    @Then("the response will return status {int} and id {int} and email {string} and first name {string} and last name {string}")
    public void verifyStatus(int expectedStatusCode, int expectedId, String expectedEmail, String expectedFirstName, String expectedLastName){

        validatableResponse.assertThat().statusCode(expectedStatusCode);

        validatableResponse.assertThat().body("data.id",equalTo(expectedId));

        validatableResponse.assertThat().body("data.email",equalTo(expectedEmail));

        validatableResponse.assertThat().body("data.first_name",equalTo(expectedFirstName));

        validatableResponse.assertThat().body("data.last_name",equalTo(expectedLastName));

    }
}

In order to use REST assured effectively it’s recommended to statically import methods from the following classes:

io.restassured.RestAssured.*
io.restassured.matcher.RestAssuredMatchers.*
org.hamcrest.Matchers.*

There is another way to perform these assertions. We can use multiple body assertions together.

@Then("the response will return status {int} and id {int} and email {string} and first name {string} and last name {string}")
    public void verifyStatus(int expectedStatusCode, int expectedId, String expectedEmail, String expectedFirstName, String expectedLastName){

   validatableResponse.assertThat().statusCode(expectedStatusCode).body("data.id",equalTo(expectedId)).and()
                .body("data.email",equalTo(expectedEmail)).body("data.first_name",equalTo(expectedFirstName))
                .body("data.last_name",equalTo(expectedLastName));

Step 11 – Create a JUnit Cucumber Runner class

A runner will help us to run the feature file and act as an interlink between the feature file and StepDefinition Class.

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

@RunWith(Cucumber.class)
@CucumberOptions(features= {"src/test/resources"}, glue= {"com.example.stepdefinitions"})
public class CucumberRunnerTests {
}

Note:- The name of the Runner class should end with Test otherwise we can’t run the tests using Command-Line.

Step 12 – Run the tests from JUnit

You can execute the test script by right-clicking on TestRunner class -> Run As JUnit (Eclipse).

Step 13 – Run the tests from the Command Line

Run the below command in the command prompt to run the tests and to get the test execution report.

mvn clean test

Step 14 – Cucumber Report Generation

To get Cucumber Test Reports, add cucumber.properties under src/test/resources and add the below instruction in the file.

cucumber.publish.enabled=true

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

How to print pretty JSON using org.json library in Java? 
Integration of REST Assured with JUnit4
Integration of REST Assured with JUnit5 
Logging in Rest Assured
Serenity BDD with Cucumber and Rest Assured in Gradle
How To Create Gradle Project with Cucumber to test Rest API

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 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

How to install Maven Plugin in Jenkins

HOME

In this tutorial, we are going to learn how we can install the Maven plugin and create a Maven project in Jenkins.

Implementation Steps

Step 1: Create a project for running the tests using Selenium WebDriver and TestNG

Step 2: Create the Test Code

You can refer to this tutorial to get the test code – Integration Of Jenkins With Selenium WebDriver.

Step 3: Start the Jenkins server

Open the browser and navigate to the localhost and the port in which Jenkins is running.

http://localhost:8080/

Step 4: Log in to Jenkins UI

Provide username and password and click on Sign in.

Step 5: Download and Install Maven Plugin

Click on the Manage Jenkins.

Choose Manage Plugins.

Step 6: Add the Maven Integration plugin

On the Plugins Page, go to the Available option

  1. Select the Maven Integration Plugin
  2. Click on Install without restartThe plugin will take a few moments to finish downloading depending on your internet connection, and will be installed automatically.
  3. You can also select the option Download now and Install after the restart button. In which plugin is installed after the restart
  4. You will be shown a “No updates available” message if you already have the Maven plugin installed.

The plugin “Maven Integration” has been installed successfully.

Step 7: Restart Jenkins

Click on the checkbox “Restart Jenkins when installation is complete when no jobs are running“.

The Jenkins is being restarted, It is about to restart.

Again, log in to Jenkins UI.

Step 8: Create a new project using the Maven project plugin

  1. Give the Name of the project – SeleniumTestNG_MavenDemo.
  2. Click on the Maven project. 
  3. Click on the OK button.

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

Step 9: Build Management

Go to the Build section of the new job.

  • In the Root POM textbox, enter the full path to pom.xml
  • In the Goals and options section, enter “clean test

Click on the Apply and Save buttons.

We have created a new Maven project SeleniumTestNG_MavenDemo” with the configuration to run the Selenium with TestNG Tests

 Step 10: Execute the tests

Click on the Build Now link. Maven will build the project. It will then have TestNG execute the test cases.

To see the current status of the execution, click on the “console output“.

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

Additional Tutorials

How to install Plugins from Jenkins CLI?
Integrate Gradle project with Jenkins
How to generate TestNG Report in Jenkins
How to create Jenkins pipeline for Selenium tests
 Integration of GitHub with Jenkins

How to print pretty JSON using org.json library in Java?

HOME

public java.lang.String toString(int indentFactor)

import org.json.JSONArray;
import org.json.JSONObject;
import org.junit.Test;


public class Json_Demo {

    @Test
    public void passBodyAsJsonArray1() {

        // Creating JSON array to add first JSON object
        JSONArray array1 = new JSONArray();
        array1.put(new JSONObject().put("firstname", "Tom").put("lastname", "Mathew").put("age", 59).put("salary",
                720000));

        // Creating JSON array
        JSONArray array2 = new JSONArray();
        array2.put(new JSONObject().put("firstname", "Perry").put("lastname", "David").put("age", 32).put("salary",
                365000));

        // Create JSON Object to add JSONArrays
        JSONObject data1 = new JSONObject();
        data1.put("employee1", array1);
        data1.put("employee2", array2);

        System.out.println(data1);

    }
}

import org.json.JSONArray;
import org.json.JSONObject;
import org.junit.Test;

public class Json_Demo {

    @Test
    public void passBodyAsJsonArray1() {

        // Creating JSON array to add first JSON object
        JSONArray array1 = new JSONArray();
        array1.put(new JSONObject().put("firstname", "Tom").put("lastname", "Mathew").put("age", 59).put("salary",
                720000));

        // Creating JSON array
        JSONArray array2 = new JSONArray();
        array2.put(new JSONObject().put("firstname", "Perry").put("lastname", "David").put("age", 32).put("salary",
                365000));

        // Create JSON Object to add JSONArrays
        JSONObject data1 = new JSONObject();
        data1.put("employee1", array1);
        data1.put("employee2", array2);

        System.out.println(data1.toString(4));

    }
}

Cucumber Tutorial – What is Feature File in Cucumber

HOME

In the previous tutorial, we discussed How Cucumber can be setup with Eclipse. In this tutorial, we will discuss the Feature files. 

What is a Feature File?

Cucumber tests are grouped into features. A Feature file is one in which we store a description of the features and scenarios to be tested. It is used to provide a high-level description of test scenarios and group-related scenarios. A Feature File is an entry point to the Cucumber tests.

The first keyword in the Feature file is the Feature keyword, followed by: and short text that describes the feature.

You can add free-form text underneath the Feature to add more description.

These description lines are ignored by Cucumber at runtime, but are available for reporting (They are included by default in HTML reports).

The name and the optional description have no special meaning to Cucumber. Their purpose is to provide a place for you to document important aspects of the feature, such as a brief explanation and a list of business rules (general acceptance criteria).

The free format description for Feature ends when you start a line with the keyword Example or Scenario Outline (or their alias keywords).

You can place tags above Feature to group related features, independent of your file and directory structure.

A simple feature file consists of the following keywords/parts −

  • FeatureFile Name – Name of the feature under test. For example, here is LoginPage.feature
  • Feature − Describe the feature under test, like here “Login to HRM Application”
  • Scenario − What is the test scenario we want to test
  • Given − Prerequisite before the test steps get executed.
  • When − Specific condition that should match to execute the next step.
  • Then − What should happen if the condition mentioned in WHEN is satisfied
  • And/But – If we have several Given’s, When’s, or Then’s, then we can use And /But

Steps to create a Feature file

Step 1 – Create a new Maven project.

<dependency>
      <groupId>io.cucumber</groupId>
      <artifactId>cucumber-java</artifactId>
      <version>7.14.0</version>
</dependency>

Step 3 – It is suggested to create the Feature files in the src/test/resources source folder. By default, this folder is not present. So, first, create a Source Folder named src/test/resources. Right-click on the project, and select New → Source Folder.

Provide the name to the Source Folder and click on the Finish button.

This creates a new Source Folder.

Step 4 –We want all our Feature files to be present inside a folder. So, create a new folder with the name Features in the src/test/resources folder.

Step 5 – Create a Feature file in the features package.

Right-click on the Feature folder, select New ->File and mention the name LoginPage.feature. Click the Finish button. (Remember to add .feature at the end of the file, otherwise, this feature file will be just an ordinary plain text file).

The below image is an example of the new feature file created. This sample feature file gives an idea how what an actual Feature file should look like.

Below is an example of a valid feature file.

@LoginPage
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

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!!