API Automation Testing with Pytest, Requests, and Allure: A Step‑by‑Step Guide
This guide walks through setting up a Python environment, organizing a test project, writing reusable request utilities and data‑driven Pytest cases, generating Allure reports, and extending tests with token handling and database verification for robust backend API automation.
1. Environment preparation Install the required Python libraries with pip install pytest requests allure-pytest pytest-html .
2. Project directory structure A typical API test project layout includes folders such as config/ , test_cases/ , utils/ , data/ , and configuration files like conftest.py , pytest.ini , and requirements.txt :
api_test_project/
├── config/
│ └── config.yaml # environment config
├── test_cases/
│ ├── __init__.py
│ ├── test_login.py # login API test
│ └── test_user.py # user management API test
├── utils/
│ ├── __init__.py
│ ├── request_util.py # wrapper for Requests
│ └── assert_util.py # custom assertions
├── data/
│ ├── login_data.json # login parameters
│ └── user_data.csv
├── conftest.py # global fixtures
├── pytest.ini # pytest config
└── requirements.txt # dependencies3. Writing test cases
3.1 Request utility Create a reusable class to send GET/POST requests:
import requests
class RequestUtil:
def send_request(self, method, url, headers=None, data=None, json=None):
if method.upper() == "GET":
return requests.get(url, headers=headers, params=data)
elif method.upper() == "POST":
return requests.post(url, headers=headers, data=data, json=json)
else:
raise ValueError("Unsupported HTTP method")3.2 Test case for login Define a fixture for the base URL and write a login test using the utility:
import pytest
from utils.request_util import RequestUtil
@pytest.fixture(scope="session")
def base_url():
return "https://api.example.com"
def test_login(base_url):
url = f"{base_url}/login"
data = {"username": "admin", "password": "123456"}
response = RequestUtil().send_request("POST", url, json=data)
assert response.status_code == 200
assert response.json()["msg"] == "success"3.3 Data‑driven testing Use @pytest.mark.parametrize to run the same test with multiple credential sets:
import pytest
from utils.request_util import RequestUtil
@pytest.mark.parametrize("username, password, expected_msg", [
("admin", "123456", "success"),
("admin1", "1234561", "用户名或密码错误"),
("admin2", "1234562", "用户名或密码错误")
])
def test_login(base_url, username, password, expected_msg):
url = f"{base_url}/login"
data = {"username": username, "password": password}
response = RequestUtil().send_request("POST", url, json=data)
assert response.status_code == 200
assert response.json()["msg"] == expected_msg4. Generating Allure reports Run tests and produce an Allure report with:
pytest --alluredir=./results --clean-alluredir
allure serve ./results
# or generate an HTML report
pytest --html=report.html5. Advanced extensions
5.1 Token acquisition and reuse Create a session‑scoped fixture that logs in, extracts the token, and returns it for other tests:
import pytest
from utils.request_util import RequestUtil
@pytest.fixture(scope="session")
def auth_token(base_url):
url = f"{base_url}/login"
data = {"username": "admin", "password": "123456"}
response = RequestUtil().send_request("POST", url, json=data)
token = response.json()["token"]
return tokenUse the token in subsequent requests:
def test_user_info(auth_token, base_url):
url = f"{base_url}/user/1"
headers = {"Authorization": f"Bearer {auth_token}"}
response = RequestUtil().send_request("GET", url, headers=headers)
assert response.status_code == 2005.2 Database verification Define a simple DB utility with SQLAlchemy to query the database and assert results after API actions:
from sqlalchemy import create_engine
class DBUtil:
def __init__(self, db_url):
self.engine = create_engine(db_url)
def query_user(self, user_id):
with self.engine.connect() as conn:
result = conn.execute(f"SELECT * FROM users WHERE id = {user_id}")
return result.fetchone()
def test_create_user(auth_token, base_url):
url = f"{base_url}/users"
headers = {"Authorization": f"Bearer {auth_token}"}
data = {"name": "Alice"}
response = RequestUtil().send_request("POST", url, headers=headers, json=data)
user_id = response.json()["id"]
db_util = DBUtil("mysql://user:pass@localhost/db")
user = db_util.query_user(user_id)
assert user["name"] == "Alice"6. Summary By combining Pytest, Requests, and Allure, you can build efficient, maintainable, and extensible API automation suites that support data‑driven testing, token management, and database validation, providing clear reports for continuous integration and team collaboration.
Test Development Learning Exchange
Test Development Learning Exchange
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.