Cucumber Integration with REST-assured: Automating API Tests

What is Cucumber Integration with REST-assured?

Cucumber with REST-assured combines Cucumber’s human-readable Gherkin scenarios with REST-assured’s Java library for testing RESTful APIs. Cucumber defines test scenarios in plain language, while REST-assured handles HTTP requests (e.g., GET, POST) and validates responses (e.g., status codes, JSON data). This integration enables collaborative API testing, ensuring backend services meet requirements.

Why Use Cucumber with REST-assured?


Setting Up a Cucumber-REST-assured Project

Let’s set up a Maven project, create a feature file, and integrate REST-assured to automate an API test scenario. This example tests a public API (e.g., reqres.in), which provides mock endpoints for learning.

Step 1: Create a Maven Project

Create a new Maven project in your IDE (e.g., IntelliJ) with the following pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>cucumber-restassured-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- Cucumber Dependencies -->
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-java</artifactId>
            <version>7.18.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-junit</artifactId>
            <version>7.18.0</version>
            <scope>test</scope>
        </dependency>
        <!-- REST-assured Dependency -->
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
            <version>5.5.0</version>
            <scope>test</scope>
        </dependency>
        <!-- JUnit Dependency -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.5.0</version>
            </plugin>
        </plugins>
    </build>
</project>

Step 2: Create a Feature File

Create a file named user_api.feature in src/test/resources/features:

Feature: User API
  As a client, I want to interact with the user API so that I can manage user data.

  Scenario: Retrieve a user by ID
    Given the API endpoint is "https://reqres.in/api/users/2"
    When the client sends a GET request
    Then the response status code should be 200
    And the response should contain the user email "janet.weaver@reqres.in"

Explanation:

Step 3: Create Step Definitions with REST-assured

Create UserApiSteps.java in src/test/java/steps:

package steps;

import io.cucumber.java.en.Given;
import io.cucumber.java.en.When;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.And;
import io.restassured.RestAssured;
import io.restassured.response.Response;
import org.junit.Assert;

public class UserApiSteps {
    private Response response;

    @Given("the API endpoint is {string}")
    public void setApiEndpoint(String endpoint) {
        RestAssured.baseURI = endpoint;
    }

    @When("the client sends a GET request")
    public void sendGetRequest() {
        response = RestAssured.get();
    }

    @Then("the response status code should be {int}")
    public void verifyStatusCode(int expectedStatusCode) {
        int actualStatusCode = response.getStatusCode();
        Assert.assertEquals("Status code mismatch", expectedStatusCode, actualStatusCode);
    }

    @And("the response should contain the user email {string}")
    public void verifyUserEmail(String expectedEmail) {
        String actualEmail = response.jsonPath().getString("data.email");
        Assert.assertEquals("Email mismatch", expectedEmail, actualEmail);
    }
}

Explanation:

Step 4: Create a Test Runner

Create TestRunner.java in src/test/java:

package runner;

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

@RunWith(Cucumber.class)
@CucumberOptions(
    features = "src/test/resources/features",
    glue = "steps",
    plugin = {
        "pretty",
        "html:reports/cucumber.html",
        "json:reports/cucumber.json"
    },
    monochrome = true
)
public class TestRunner {
}

Step 5: Run the Tests

Run the tests using Maven:

mvn test

Output:

Setting API endpoint: https://reqres.in/api/users/2
Sending GET request
Verifying status code: 200
Verifying user email: janet.weaver@reqres.in

1 Scenario (1 passed)
4 Steps (4 passed)
0m1.234s

Reports:


Enhancing the Integration

Let’s explore advanced techniques to make the Cucumber-REST-assured integration more robust.

Example 1: Testing a POST Request

Update user_api.feature to include a POST scenario:

Feature: User API
  As a client, I want to interact with the user API so that I can manage user data.

  Scenario: Retrieve a user by ID
    Given the API endpoint is "https://reqres.in/api/users/2"
    When the client sends a GET request
    Then the response status code should be 200
    And the response should contain the user email "janet.weaver@reqres.in"

  Scenario: Create a new user
    Given the API endpoint is "https://reqres.in/api/users"
    When the client sends a POST request with the following data
      | name | John Doe |
      | job  | Developer |
    Then the response status code should be 201
    And the response should contain the name "John Doe"

Update UserApiSteps.java:

import io.cucumber.datatable.DataTable;
import java.util.Map;

@When("the client sends a POST request with the following data")
public void sendPostRequest(DataTable dataTable) {
    Map<String, String> data = dataTable.asMaps().get(0);
    response = RestAssured.given()
        .contentType("application/json")
        .body(data)
        .post();
}

@And("the response should contain the name {string}")
public void verifyUserName(String expectedName) {
    String actualName = response.jsonPath().getString("name");
    Assert.assertEquals("Name mismatch", expectedName, actualName);
}

Explanation:

Run the tests:

mvn test

Output:
The HTML report will show both scenarios passed.

Example 2: Using Scenario Hooks

Add hooks to log request/response details for debugging. Create ApiHooks.java in src/test/java/steps:

package steps;

import io.cucumber.java.Before;
import io.cucumber.java.After;
import io.restassured.RestAssured;
import io.restassured.filter.log.RequestLoggingFilter;
import io.restassured.filter.log.ResponseLoggingFilter;

public class ApiHooks {
    @Before
    public void setUp() {
        RestAssured.filters(new RequestLoggingFilter(), new ResponseLoggingFilter());
    }

    @After
    public void tearDown() {
        RestAssured.reset();
    }
}

Explanation:

Example 3: Reusable Request Specification

Create a reusable RequestSpecification for common settings (e.g., base URI, headers). Create ApiConfig.java in src/test/java/config:

package config;

import io.restassured.builder.RequestSpecBuilder;
import io.restassured.specification.RequestSpecification;

public class ApiConfig {
    public static RequestSpecification getRequestSpec(String baseUri) {
        return new RequestSpecBuilder()
            .setBaseUri(baseUri)
            .setContentType("application/json")
            .build();
    }
}

Update UserApiSteps.java:

@Given("the API endpoint is {string}")
public void setApiEndpoint(String endpoint) {
    RestAssured.requestSpecification = ApiConfig.getRequestSpec(endpoint);
}

@When("the client sends a POST request with the following data")
public void sendPostRequest(DataTable dataTable) {
    Map<String, String> data = dataTable.asMaps().get(0);
    response = RestAssured.given()
        .body(data)
        .post();
}

Explanation:


Best Practices for Cucumber-REST-assured Integration

  1. Use Data Tables: Pass complex request data using Cucumber Data Tables.
  2. Centralize Configuration: Use RequestSpecification for reusable API settings.
  3. Log Requests/Responses: Enable logging in hooks for debugging.
  4. Validate Responses: Check status codes, headers, and body content thoroughly.
  5. Keep Steps Focused: Write Gherkin steps for API behavior, not implementation details.
  6. Handle Authentication: Use REST-assured’s auth() methods for OAuth, Basic Auth, or tokens:
    RestAssured.given().auth().basic("username", "password").get();
    

Troubleshooting Cucumber-REST-assured Issues


Tips for Beginners

🤖
PrepCampusPlus AI Tutor
Scroll to Top