Cucumber - API Testing

Cucumber: API Testing Explained

API testing with Cucumber allows you to validate the functionality, performance, and reliability of APIs by combining behavior-driven development (BDD) with API automation tools like RestAssured. This approach ensures your APIs meet business requirements in a human-readable format.

Why Use Cucumber for API Testing?

Cucumber’s Gherkin syntax enables non-technical stakeholders to understand and contribute to test scenarios. Integrating Cucumber with API testing tools helps:

  • Bridge the gap between technical and non-technical teams.
  • Ensure test cases align with business requirements.
  • Validate APIs for functionality, data integrity, and edge cases.

Setting Up Cucumber for API Testing

1. Project Setup:

Create a Maven or Gradle project and add the following dependencies:


                  <dependency>
                    <groupId>io.cucumber</groupId>
                    <artifactId>cucumber-java</artifactId>
                    <version>X.X.X</version>
                  </dependency>
                  <dependency>
                    <groupId>io.cucumber</groupId>
                    <artifactId>cucumber-junit</artifactId>
                    <version>X.X.X</version>
                  </dependency>
                  <dependency>
                    <groupId>io.rest-assured</groupId>
                    <artifactId>rest-assured</artifactId>
                    <version>X.X.X</version>
                  </dependency>
                

2. Define Feature Files:

Write feature files to describe API tests in Gherkin syntax. For example, testing a user login API might look like this:


                  Feature: User Login API
              
                  Scenario: Valid login credentials
                    Given the login API endpoint is "https://api.example.com/login"
                    When the user submits valid credentials
                    Then the API response code should be 200
                    And the response body should contain "token"
                

3. Step Definitions:

Implement step definitions using RestAssured to handle HTTP requests and responses:


                  import io.restassured.RestAssured;
                  import io.restassured.response.Response;
                  import static org.hamcrest.Matchers.*;
              
                  public class ApiStepDefinitions {
                      private String endpoint;
                      private Response response;
              
                      @Given("the login API endpoint is {string}")
                      public void setApiEndpoint(String url) {
                          endpoint = url;
                      }
              
                      @When("the user submits valid credentials")
                      public void submitValidCredentials() {
                          response = RestAssured
                              .given()
                              .contentType("application/json")
                              .body("{ \"username\": \"user1\", \"password\": \"password123\" }")
                              .post(endpoint);
                      }
              
                      @Then("the API response code should be {int}")
                      public void verifyResponseCode(int statusCode) {
                          response.then().statusCode(statusCode);
                      }
              
                      @Then("the response body should contain {string}")
                      public void verifyResponseBody(String key) {
                          response.then().body("", hasKey(key));
                      }
                  }
                

4. Run the Tests:

Use a test runner class annotated with @RunWith(Cucumber.class) to execute the scenarios:


                  import org.junit.runner.RunWith;
                  import io.cucumber.junit.Cucumber;
                  import io.cucumber.junit.CucumberOptions;
              
                  @RunWith(Cucumber.class)
                  @CucumberOptions(features = "src/test/resources/features", glue = "stepdefinitions")
                  public class ApiTestRunner {
                  }
                

Real-World Scenario:

Imagine testing a product search API in an e-commerce platform. The API should return product details when valid search terms are provided.

Feature File:

                  Scenario: Search for a product by name
                    Given the search API endpoint is "https://api.example.com/search"
                    When the user searches for "laptop"
                    Then the API response code should be 200
                    And the response body should include a product with the name "laptop"
                
Step Definitions:

                  @When("the user searches for {string}")
                  public void searchProduct(String productName) {
                      response = RestAssured
                          .given()
                          .queryParam("query", productName)
                          .get(endpoint);
                  }
              
                  @Then("the response body should include a product with the name {string}")
                  public void verifyProductInResponse(String productName) {
                      response.then().body("products.name", hasItem(productName));
                  }
                

Best Practices

  • Use environment variables to manage API endpoints and credentials.
  • Test all possible response codes (e.g., 200, 400, 401, 500).
  • Mock external APIs during development to isolate functionality.
  • Validate response times for performance testing.