Advanced
Chapter 17 · 11 min read
API Testing with Cucumber
Write BDD scenarios for REST API testing — combine Gherkin with HTTP clients for API validation without a browser.
API Testing with Cucumber
Cucumber isn't just for UI testing. BDD scenarios work beautifully for API testing — expressing expected API behavior in business-readable Gherkin while executing HTTP requests under the hood.
api.feature
Feature: User API
@api
Scenario: Get all users
Given the API base URL is "https://jsonplaceholder.typicode.com"
When I send a GET request to "/users"
Then the response status code should be 200
And the response should contain 10 users
@api
Scenario: Create a new user
Given the API base URL is "https://jsonplaceholder.typicode.com"
When I send a POST request to "/posts" with:
| title | BDD API Testing |
| body | Testing APIs with Gherkin |
| userId | 1 |
Then the response status code should be 201
And the response should contain "id"
@api
Scenario: Get user by ID
Given the API base URL is "https://jsonplaceholder.typicode.com"
When I send a GET request to "/users/1"
Then the response status code should be 200
And the response field "name" should be "Leanne Graham"
ApiSteps.java
package com.bdd.course.stepdefinitions;
import io.cucumber.java.en.*;
import io.cucumber.datatable.DataTable;
import io.restassured.RestAssured;
import io.restassured.response.Response;
import static org.hamcrest.Matchers.*;
import java.util.Map;
public class ApiSteps {
private String baseUrl;
private Response response;
@Given("the API base URL is {string}")
public void setBaseUrl(String url) {
this.baseUrl = url;
}
@When("I send a GET request to {string}")
public void sendGet(String endpoint) {
response = RestAssured.given()
.baseUri(baseUrl)
.when().get(endpoint);
}
@When("I send a POST request to {string} with:")
public void sendPost(String endpoint, DataTable table) {
Map<String, String> body = table.asMap(String.class, String.class);
response = RestAssured.given()
.baseUri(baseUrl)
.contentType("application/json")
.body(body)
.when().post(endpoint);
}
@Then("the response status code should be {int}")
public void verifyStatusCode(int expected) {
response.then().statusCode(expected);
}
@Then("the response should contain {int} users")
public void verifyUserCount(int count) {
response.then().body("size()", equalTo(count));
}
@Then("the response should contain {string}")
public void responseContainsField(String field) {
response.then().body(field, notNullValue());
}
@Then("the response field {string} should be {string}")
public void responseFieldEquals(String field, String value) {
response.then().body(field, equalTo(value));
}
}
api.feature
Feature: User API
@api
Scenario: Get all users
Given the API base URL is "https://jsonplaceholder.typicode.com"
When I send a GET request to "/users"
Then the response status code should be 200
And the response should contain 10 users
@api
Scenario: Create a new user
Given the API base URL is "https://jsonplaceholder.typicode.com"
When I send a POST request to "/posts" with:
| title | BDD API Testing |
| body | Testing APIs with Gherkin |
| userId | 1 |
Then the response status code should be 201
api_steps.py
# features/steps/api_steps.py
import requests
from behave import given, when, then
@given('the API base URL is "{url}"')
def step_base_url(context, url):
context.base_url = url
@when('I send a GET request to "{endpoint}"')
def step_get(context, endpoint):
context.response = requests.get(f'{context.base_url}{endpoint}')
@when('I send a POST request to "{endpoint}" with')
def step_post(context, endpoint):
body = {row['key']: row['value'] for row in context.table}
# Alternative: if table has named columns
if hasattr(context.table, 'headings') and len(context.table.headings) == 2:
body = {}
for row in context.table:
body[row[0]] = row[1]
context.response = requests.post(
f'{context.base_url}{endpoint}', json=body)
@then('the response status code should be {code:d}')
def step_status(context, code):
assert context.response.status_code == code
@then('the response should contain {count:d} users')
def step_user_count(context, count):
assert len(context.response.json()) == count
@then('the response field "{field}" should be "{value}"')
def step_field_equals(context, field, value):
assert context.response.json()[field] == value
Cucumber BDD
Advanced
API Testing with Cucumber
Written by PV
© 2026 All Rights Reserved