- Published on
API Testing with Cucumber BDD
API Testing with Cucumber BDD
API testing is crucial for ensuring that the backend of an application works as expected, reliably, and efficiently. Behavior Driven Development (BDD) with Cucumber allows teams to create tests in a human-readable format, promoting collaboration and clarity. In this post, we'll explore how to set up API testing using Cucumber, write BDD scenarios, and implement step definitions for testing APIs.
Table of Contents
- 1. Introduction to API Testing with Cucumber BDD
- 2. Setting Up a Project for API Testing with Cucumber
- 3. Writing Gherkin Scenarios for API Testing
- 4. Implementing Step Definitions for API Testing
- 5. Running Cucumber Tests
- 6. Advanced Cucumber Features for API Testing
- 7. Best Practices for API Testing with Cucumber BDD
- 8. Integrating Cucumber with CI/CD Pipelines
- 9. Conclusion
- 10. Further Reading and Resources
1. Introduction to API Testing with Cucumber BDD
API testing focuses on validating the business logic, data responses, and performance of server-side endpoints. Cucumber, a BDD tool, allows tests to be written in Gherkin, a plain-text language that makes tests understandable for non-technical stakeholders. Using Cucumber for API testing encourages collaboration between developers, testers, and business analysts, ensuring everyone is on the same page.
2. Setting Up a Project for API Testing with Cucumber
Step-by-Step Setup:
Install Required Tools:
- Install Java Development Kit (JDK) and Maven (for Java projects).
- Install an IDE like IntelliJ IDEA or Eclipse.
- Install Cucumber and REST Assured dependencies for API testing.
Configure Maven Project:
- Create a new Maven project and add the following dependencies to your
pom.xml
file:
- Create a new Maven project and add the following dependencies to your
<dependencies>
<!-- Cucumber Dependencies -->
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>7.14.0</version>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>7.14.0</version>
</dependency>
<!-- REST Assured Dependency for API Testing -->
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>5.3.0</version>
</dependency>
</dependencies>
- Create the Project Structure:
- Organize the project with
src/test/java
for step definitions andsrc/test/resources
for feature files.
- Organize the project with
3. Writing Gherkin Scenarios for API Testing
Create a feature file named user_api.feature
in the src/test/resources/features
directory.
Feature: User API
Scenario: Create a new user successfully
Given the API endpoint is set to "/users"
When a POST request is sent with valid user data
Then the response status code should be 201
And the response body should contain the user's information
Scenario: Fetch user details successfully
Given the API endpoint is set to "/users/{id}"
When a GET request is sent for user with ID "1"
Then the response status code should be 200
And the response body should contain the user's information
Scenario: User not found when fetching details
Given the API endpoint is set to "/users/{id}"
When a GET request is sent for user with ID "999"
Then the response status code should be 404
And the response body should contain "User not found"
4. Implementing Step Definitions for API Testing
Step definitions map Gherkin steps to Java methods using REST Assured for HTTP requests. Create a Java class named UserApiSteps.java
under src/test/java/step_definitions
.
package step_definitions;
import io.cucumber.java.en.*;
import io.restassured.RestAssured;
import io.restassured.response.Response;
import io.restassured.specification.RequestSpecification;
import org.junit.Assert;
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.*;
public class UserApiSteps {
private static final String BASE_URL = "https://example.com/api";
private RequestSpecification request;
private Response response;
private String endpoint;
@Given("the API endpoint is set to {string}")
public void the_api_endpoint_is_set_to(String endpoint) {
this.endpoint = BASE_URL + endpoint;
RestAssured.baseURI = BASE_URL;
request = given().header("Content-Type", "application/json");
}
@When("a POST request is sent with valid user data")
public void a_post_request_is_sent_with_valid_user_data() {
String requestBody = "{ \"name\": \"John Doe\", \"email\": \"[email protected]\" }";
response = request.body(requestBody).post(endpoint);
}
@When("a GET request is sent for user with ID {string}")
public void a_get_request_is_sent_for_user_with_id(String userId) {
response = request.get(endpoint.replace("{id}", userId));
}
@Then("the response status code should be {int}")
public void the_response_status_code_should_be(int statusCode) {
response.then().statusCode(statusCode);
}
@Then("the response body should contain the user's information")
public void the_response_body_should_contain_user_information() {
response.then().body("name", notNullValue()).body("email", notNullValue());
}
@Then("the response body should contain {string}")
public void the_response_body_should_contain(String message) {
Assert.assertTrue(response.getBody().asString().contains(message));
}
}
5. Running Cucumber Tests
To run the Cucumber tests, use a test runner class. Create a Java class named RunCucumberTest.java
under src/test/java/runner
.
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 = "step_definitions",
plugin = {"pretty", "html:target/cucumber-reports"}
)
public class RunCucumberTest {
}
Run the RunCucumberTest
class to execute the scenarios. The results will be displayed in the console, and an HTML report will be generated in the target/cucumber-reports
folder.
6. Advanced Cucumber Features for API Testing
Using Hooks:
Hooks allow you to perform actions before and after each scenario, such as setting up or tearing down a test environment.
import io.cucumber.java.After;
import io.cucumber.java.Before;
public class Hooks {
@Before
public void setUp() {
// Set up code, like initializing RestAssured configurations
RestAssured.baseURI = "https://example.com/api";
}
@After
public void tearDown() {
// Code to clean up or reset the state
}
}
7. Best Practices for API Testing with Cucumber BDD
- Organize Feature Files and Steps: Keep related API scenarios together and use descriptive names.
- Use Data Tables for Input Variations: Utilize Cucumber's Data Tables to handle different test data combinations without repeating steps.
- Ensure Idempotency: Make sure API tests are idempotent and do not affect each other, using setup and teardown methods wisely.
8. Integrating Cucumber with CI/CD Pipelines
To integrate Cucumber with CI/CD pipelines like Jenkins or GitHub Actions, configure the pipeline to run mvn test
and archive the test reports generated in the target/cucumber-reports
directory.
9. Conclusion
API testing with Cucumber BDD provides a readable, maintainable approach to validating the business logic and performance of backend services. By writing scenarios in plain English, you can ensure everyone on the team understands and contributes to the testing process.
10. Further Reading and Resources
By following this guide, you should be able to set up API testing with Cucumber, write effective Gherkin scenarios, implement robust step definitions, and run tests seamlessly.