API Test Automation With RestAssured Library and Cucumber BDD Framework

Introduction to Rest Assured Library

REST (Representational State Transfer) is an architecture that consumes HTTP calls for inter-system communication where a client can access the server resource with a unique URI, and the response of the resource is returned. The URI of the resource acts as a resource identifier, and HTTP operations like GET, POST, PUT, PATCH, and DELETE can be performed on the resource.

REST Assured is a Java library that leverages developing robust, maintainable tests for Restful APIs with domain-specific language(DSL). Let’s discuss some of the salient features of the Rest Assured Library:

  1. It’s an open-source application; hence, there’s no license cost
  2. Uses the commonly used programming language Java
  3. It makes API testing and validation of Rest services easy and smooth
  4. GPath is used to traverse through the response, which is excellent for both XML and JSON response read
  5. Validations on JSON schema can be applied
  6. Effortless integration can be done with other testing frameworks such as TestNG, JUnit, etc
  7. Supports API automation for all types of HTTP methods such as GET, POST, PUT, DELETE, PATCH, etc
  8. Provides support for BDD Gherkin language, which leads to clean coding and easy readability

Introduction to Cucumber Framework

Cucumber is an open-source testing framework that supports Behavior Driven Development (BDD) and is a widely used framework that testers leverage to write test cases in simple English language called Gherkin.

To make the testing process and flow easily understandable by non-techies, many organizations want to integrate the Cucumber framework with Selenium or Rest Assured for application automation. Since Cucumber allows writing tests and scenarios in simple English plain text, it becomes a primary advantage for many team members who are Business Analysts, Project Managers, Manual Testers, and for any other non-technical persons to view and understand the testing workflow with much ease. Cucumber is //.[known as Behavior Driven Development (BDD) framework as it can help anyone grab the functional behavior of an application by just reading out the feature file.

The Cucumber Framework Is Divided Into Three Different Components:

1. Feature File: This file provides high-level information about an application under test in the form of test features, test scenarios, test tags, test cases, test data, etc. Below are few a components that are used to create a feature file:

  • Feature- Defines the feature planned to be tested along with its objective.
  • Scenario- Defines the particular test scenario for which test flow must be created.
  • Scenario Outline- Defines the particular test scenario against different test data provided in a tabular structure separated by a pipe symbol( | )
  • Tags- Defines the tag’s name for each scenario, which helps organize or group all the test scenarios of the feature file. Tags can be used on the above Feature keyword to indicate which feature file needs to be executed.
  • Given- Defines pre-condition of a particular test scenario
  • When- Defines an action or interaction with an application yet to be performed
  • And- Defines extra action related linked with the previous action
  • Then- Defines the expected output of the test and the post-action to be performed
  • Examples- Define a test data set for the test case written in “Scenario Outline.”

2. Step Definition File: The step definitions file is created to link all the feature file test case steps to code. Few annotations like Given, When, Then, etc., are used in step definition files to map the test case steps for their code execution. For a test case to be executed, the annotated description must match the test step mentioned in the feature file.

3. Test Runner File: This file is a driver file for your test suite that drives or runs the step definition files based on feature files. The Test Runner file consists of the paths to your feature and step definition file along with the tags to be executed and required for cucumber-based test reporting. For cucumber-based HTML reporting, it also provides you an option to add a plugin to generate insightful reports.

Integrating Rest Assured Library With Cucumber Framework

Now that we are aware of the Rest Assured library and Cucumber framework let’s practically understand how we can create the test scenarios and learn the steps for API testing against different sets of test data. As discussed earlier, to integrate the rest assured library with the cucumber framework, we need to create other files like feature, step definition, and runner files.

Before moving forward, let’s create a simple maven project and import all the rest assured library’s dependencies and the cucumber framework in the pom.xml file.

<dependency>
  <groupId>info.cukes</groupId>
  <artifactId>cucumber-java</artifactId>
  <version>1.2.5</version>
</dependency>

  
<dependency>
  <groupId>info.cukes</groupId>
  <artifactId>cucumber-jvm-deps</artifactId>
  <version>1.0.5</version>
  <scope>test</scope>
  </dependency>
 
  <dependency>
  <groupId>info.cukes</groupId>
  <artifactId>cucumber-testng</artifactId>
  <version>1.2.5</version>
  <scope>compile</scope>
  <exclusions>
  <exclusion>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  </exclusion>
  </exclusions>
  </dependency>
 
  <dependency>
  <groupId>net.masterthought</groupId>
  <artifactId>cucumber-reporting</artifactId>
  <version>5.0.2</version>
  </dependency>
 
    <dependency>
  <groupId>io.rest-assured</groupId>
  <artifactId>rest-assured</artifactId>
  <version>4.3.2</version>
  <scope>test</scope>
  </dependency>

  
<dependency>
  <groupId>io.rest-assured</groupId>
  <artifactId>json-path</artifactId>
  <version>4.3.2</version>
  <scope>test</scope>
  </dependency>

 
 <dependency>
  <groupId>io.rest-assured</groupId>
  <artifactId>xml-path</artifactId>
  <version>4.3.2</version>
  <scope>test</scope>
  </dependency>

  
<dependency>
  <groupId>io.rest-assured</groupId>
  <artifactId>json-schema-validator</artifactId>
  <version>4.3.2</version>
  <scope>test</scope>
  </dependency>

  
    <dependency>
  <groupId>org.hamcrest</groupId>
  <artifactId>hamcrest-all</artifactId>
  <version>1.3</version>
  <scope>test</scope>
  </dependency>

While working with the cucumber framework, it is always recommended to have a different package for different cucumber components; this helps develop a better project hierarchy and eases the understanding of the test suite.

Feature File

Reqres_api_test.feature

Feature: Test Reqres Users API’s With Rest Assured Library And Cucumber Framework

@SmokeTest
Scenario Outline: Reqres GET API test

Given the valid endpoint to fetch users
When the request is sent to the server with page number “<page>”
Then validate the response of the first user record having email as “<emailID>”

Examples:
|page|emailID |
| 2 |michael.lawson@reqres.in|
| 1 |george.bluth@reqres.in|

@SmokeTest
Scenario Outline: Reqres POST API test

Given the valid endpoint with payload to create a user
When the request is sent to the server
Then the new user must be created with the name “<username>”

Examples:
|username|
 | john |

The goal of the above feature file is to perform parameterization testing with multiple test data. Therefore, the “Examples” keyword is used when test data has to be created, and the test data is made with a pipe symbol as a delimiter( | ). To add a parameter in a test step of a feature file, the syntax is “<variableName>”; the same has been used above. Further, the same variable name is used in the first row of Examples to segregate the test data according to specific parameters.

Step Definition File

GetApiTest.java

import static io.restassured.RestAssured.given;
import org.testng.Assert;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import io.restassured.response.Response;

public class GetApiTest {
   
    Response response;
   
    @Given("^the valid endpoint to fetch users$")
    public void setupEndpoint()
    {
  RestAssured.baseURI="https://reqres.in/";
    RestAssured.basePath="/api/users";
    }
   
   
    @When("^the request is send to server with page number as "([^"]*)"$")
    public void sendRequest(int pageNumber)
    {
  response = given().
    queryParam("page",pageNumber).
    when().
    get().
    then().
    contentType(ContentType.JSON).
    extract().response();  
    }
   
   
    @Then("^validate the response of first user record having email as "([^"]*)"$")
    public void validateUserData(String emailID)
    {
  String userEmail = response.path("data[0].email");
  Assert.assertEquals(userEmail, emailID);  
    }

PostApiTest.java

import static io.restassured.RestAssured.given;

import java.util.HashMap;

import org.testng.Assert;

import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import io.restassured.response.Response;

public class PostApiTest {
   
Response response;
public HashMap<Object,Object> map=new HashMap<Object,Object>();
   
    @Given("^the valid endpoint with payload to create user$")
    public void setupEndpointAndPostData()
    {
  RestAssured.baseURI="https://reqres.in/";
    RestAssured.basePath="/api/users";
 
    map.put("name","john");
    map.put("job", "Software Developer");
    }
   
   
    @When("^the request is send to the server$")
    public void sendRequest()
    {
  response = given()
    .contentType(ContentType.JSON)
    .body(map)   
    .when()
    .post()
    .then()
    .statusCode(201).contentType(ContentType.JSON).
    extract().response();
    }
   
   
    @Then("^the new user must be created with name as "([^"]*)"$")
    public void validateResponse(String name)
    {
  String userName = response.path("name");
  Assert.assertEquals(userName, name);  
    }

Above, we have created two-step definition files per 2 scenarios mentioned in the feature film, one for GET API validation and the other for POST API validation.

We have written an execution code for each test step defined in the feature file in our step definition file. This is the file that integrates, rest assured, with the cucumber framework as all the APIs are being validated here. The test steps written in the feature file have to be the same in the annotated descriptions with the defined way of using parameters. Further, we have used a bit of TestNG here to assert the server response.

Runner File

Runner.java

import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import cucumber.api.CucumberOptions;
import cucumber.api.testng.CucumberFeatureWrapper;
import cucumber.api.testng.TestNGCucumberRunner;

@CucumberOptions(
    features = "src/test/java/FeatureFile",
    glue = {"stepDefinitions"},
    tags = {"@SmokeTest"},
    format = {
                "pretty",
                "html:target/cucumber-reports/cucumber-pretty",
                "json:target/cucumber-reports/CucumberTestReport.json",
                "rerun:target/cucumber-reports/rerun.txt"
        },plugin = "json:target/cucumber-reports/CucumberTestReport.json")

public class Runner {
   
    private TestNGCucumberRunner testNGCucumberRunner;
   
    @BeforeClass
    public void setUp() throws Exception
    {
  testNGCucumberRunner = new TestNGCucumberRunner(Runner.class);
    }
   
   
    @Test(dataProvider="features")
      public void my_test(CucumberFeatureWrapper cucumberFeature)
    {
  testNGCucumberRunner.runCucumber(cucumberFeature.getCucumberFeature());
    }
   
   
    @DataProvider
public Object[][] features()
    {
  return testNGCucumberRunner.provideFeatures();  
    }
   
   
    @AfterClass
public void tearDown()
    {
  testNGCucumberRunner.finish();   
    }

Code Walkthrough

In our cucumber test runner file, we have a CucumberOptions annotation that accepts parameters like the path of the feature file and steps definition file along with the tags name and reporting format and the HTML reporting plugin.

To integrate the Cucumber framework with Rest Assured Library and TestNG framework, we have used a cucumber framework predefined class called “TestNGCucumberRunner,” which provides various methods such as runCucumber, provideFeatures, finish, etc. In addition, “CucumberFeatureWrapper” is an interface used in the Test annotated method parameter for making the TestNG report more descriptive.

TestNG.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">

<suite name="TestNG-Cucumber Suite" thread-count="10" parallel="tests">
    <test name="Apple test">
  <classes>
  <class name="testRunner.Runner" />
  </classes>
    </test>
</suite>

This is a TestNG XML file for configuring the test suite's execution. We have used the Runner java class to execute the API tests; once completed, the report can be visualized from the target directory -> cucumber-reports -> cucumber-pretty -> index.html.

.

Leave a Comment