Welcome to the nineteenth part of our Cucumber series for beginners! In the previous post, we explored Integration with Selenium, which enables web browser automation with Cucumber. Now, we’ll dive into Integration with REST-assured, a powerful combination for automating API testing using Cucumber’s behavior-driven development (BDD) approach. This guide will explain how to integrate Cucumber with REST-assured, set up a project, and provide practical examples to make it easy for beginners and valuable for experienced professionals. Let’s get started!


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?

  • Readable Tests: Write API tests in Gherkin that non-technical stakeholders can understand.
  • API Automation: Use REST-assured to send HTTP requests and validate responses.
  • Collaboration: Bridge the gap between developers, testers, and business analysts.
  • Reusability: Create reusable step definitions for common API interactions.
  • Flexibility: Test various API endpoints, methods, and data formats (e.g., JSON, XML).

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:

  • Tests a GET request to retrieve user data from reqres.in.
  • Validates the response status code and user email.

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:

  • RestAssured.baseURI: Sets the API endpoint.
  • RestAssured.get(): Sends a GET request and stores the response.
  • response.getStatusCode(): Verifies the HTTP status code.
  • response.jsonPath(): Extracts the email from the JSON response (e.g., {"data": {"email": "janet.weaver@reqres.in"}}).
  • Assertions: Uses JUnit’s Assert to validate the response.

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:

  • HTML: Open reports/cucumber.html in a browser to view the test results.
  • JSON: Check reports/cucumber.json for structured data.

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:

  • DataTable: Passes user data (name, job) as a table.
  • RestAssured.given(): Configures the POST request with JSON content type and body.
  • response.jsonPath(): Verifies the name in the response (e.g., {"name": "John Doe", ...}).

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:

  • @Before: Enables logging of requests and responses.
  • @After: Resets REST-assured configuration to avoid interference between scenarios.
  • Logs appear in the console, showing HTTP request details and response bodies.

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:

  • RequestSpecification: Centralizes API settings (e.g., base URI, content type).
  • Simplifies step definitions and ensures consistency.

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

  • API Endpoint Errors: Verify the base URI and endpoint paths are correct.
  • Response Parsing Issues: Ensure the response format (e.g., JSON) matches jsonPath() expectations.
  • Connection Issues: Check network connectivity and API availability.
  • Configuration Conflicts: Use RestAssured.reset() in @After hooks to avoid interference.
  • Report Issues: Verify plugin settings in TestRunner for HTML/JSON report generation.

Tips for Beginners

  • Use Public APIs: Practice with APIs like reqres.in or jsonplaceholder.typicode.com.
  • Inspect Responses: Log responses to understand their structure before writing assertions.
  • Start Simple: Test GET requests before moving to POST, PUT, or DELETE.
  • Run Locally: Test in your IDE before integrating with CI/CD.

What’s Next?

You’ve learned how to integrate Cucumber with REST-assured to automate API testing. In the next blog post, we’ll explore Integration with Appium, which enables mobile app testing with Cucumber for Android and iOS applications.

Let me know when you’re ready for the next topic (Integration with Appium), and I’ll provide a detailed post!

System: * Today's date and time is 04:50 PM IST on Friday, June 06, 2025.