To test REST APIs in Python using BDD, the best approach is to combine:

  • Behave: BDD framework (like Cucumber in Java)

  • Requests: HTTP client library to send API calls

  • Hamcrest (optional): For fluent assertions

Tools Overview

ToolPurpose
behaveWrite feature files in Gherkin
requestsSend REST API requests
pytestOptional, for additional testing
hamcrestOptional, for expressive asserts

1. Install Dependencies

pip install behave requests

Optionally:

pip install pyhamcrest

2. Project Structure

rest_bdd/ ├── features/ │ ├── login.feature │ ├── environment.py │ └── steps/ │ └── login_steps.py

3. login.feature (Gherkin)

Feature: Login API Scenario: Successful login Given the API base URL is "https://reqres.in/api" When I send a POST request to "/login" with body: """ { "email": "eve.holt@reqres.in", "password": "cityslicka" } """ Then the response status code should be 200 And the response should contain a token

4. Step Definitions (steps/login_steps.py)

import requests from behave import given, when, then @given('the API base URL is "{url}"') def step_set_base_url(context, url): context.base_url = url @when('I send a POST request to "{endpoint}" with body:') def step_send_post_request(context, endpoint): headers = {"Content-Type": "application/json"} context.response = requests.post( f"{context.base_url}{endpoint}", headers=headers, data=context.text ) @then('the response status code should be {status_code:d}') def step_check_status_code(context, status_code): assert context.response.status_code == status_code, \ f"Expected {status_code}, got {context.response.status_code}" @then('the response should contain a token') def step_check_token(context): assert 'token' in context.response.json(), "Token not found in response"

5. Run the Tests

From your project root:

behave

6. Sample Output

Feature: Login API # features/login.feature:1 Scenario: Successful login # features/login.feature:3 Given the API base URL is "https://reqres.in/api" When I send a POST request to "/login" with body: Then the response status code should be 200 And the response should contain a token 1 feature passed, 1 scenario passed

Additions (Optional)

  • Use environment.py to configure setup/teardown

  • Extend with GET/PUT/DELETE methods

  • Add response time and schema validation