project/ ├── conftest.py # pytest 全局配置和共享 Fixture ├── requirements.txt # 依赖库列表 ├── config/ │ └── settings.py # 环境配置(测试/生产环境切换) ├── tests/ # 测试用例目录 │ ├── test_user_api.py # 用户相关接口测试 │ └── test_order_api.py # 订单相关接口测试 ├── utils/ # 工具类 │ ├── http_client.py # 封装的 HTTP 请求工具 │ └── logger.py # 日志管理 └── data/ # 测试数据 └── test_data.json
在 requirements.txt
中添加:
pytest requests pytest-html # 生成HTML报告 pytest-xdist # 并行执行 python-dotenv # 环境变量管理
安装依赖:
pip install -r requirements.txt
config/settings.py
import os from dotenv import load_dotenv load_dotenv() # 加载 .env 文件 class Config: BASE_URL = os.getenv("BASE_URL", "https://api.example.com") API_KEY = os.getenv("API_KEY") # 认证密钥
utils/http_client.py
import requests from config.settings import Config class HttpClient: def __init__(self): self.base_url = Config.BASE_URL self.headers = {"Authorization": f"Bearer {Config.API_KEY}"} def get(self, endpoint, params=None): url = f"{self.base_url}{endpoint}" return requests.get(url, headers=self.headers, params=params) def post(self, endpoint, data=None): url = f"{self.base_url}{endpoint}" return requests.post(url, headers=self.headers, json=data) # 可扩展 PUT、DELETE 等方法
tests/test_user_api.py
import pytest from utils.http_client import HttpClient client = HttpClient() def test_get_user(): """测试获取用户信息""" response = client.get("/users/1") assert response.status_code == 200 assert response.json()["id"] == 1 def test_create_user(): """测试创建用户""" user_data = {"name": "Alice", "email": "[email protected]"} response = client.post("/users", data=user_data) assert response.status_code == 201 assert "id" in response.json()
import pytest test_data = [ (1, 200), # 存在的用户ID (999, 404), # 不存在的用户ID ] @pytest.mark.parametrize("user_id, expected_status", test_data) def test_get_user_status(user_id, expected_status): response = client.get(f"/users/{user_id}") assert response.status_code == expected_status
在 conftest.py
中定义共享 Fixture:
import pytest from utils.http_client import HttpClient @pytest.fixture(scope="module") def client(): """共享的 HTTP 客户端""" return HttpClient() @pytest.fixture def cleanup_user(client): """清理测试用户""" user_id = None yield user_id # 测试执行前 if user_id: # 测试执行后清理 client.delete(f"/users/{user_id}")
在测试用例中使用:
def test_create_and_delete_user(client, cleanup_user): user_data = {"name": "Bob", "email": "[email protected]"} response = client.post("/users", data=user_data) user_id = response.json()["id"] cleanup_user = user_id # 传递给 Fixture 清理 assert response.status_code == 201
pytest tests/ -v # 详细模式
pytest tests/ --html=report.html
pytest tests/ -n 4 # 启动4个进程
在 .env
文件中定义环境变量:
BASE_URL=https://test-api.example.com API_KEY=test_key
通过命令行切换环境:
BASE_URL=https://prod-api.example.com pytest tests/
使用 pytest-mock
模拟第三方服务:
def test_external_api(mocker): mock_response = mocker.Mock() mock_response.status_code = 200 mock_response.json.return_value = {"success": True} mocker.patch("requests.get", return_value=mock_response) response = client.get("/external-api") assert response.json()["success"] is True
从 JSON 文件加载测试数据:
import json import pytest with open("data/test_data.json") as f: test_data = json.load(f) @pytest.mark.parametrize("data", test_data) def test_create_users(data): response = client.post("/users", data=data) assert response.status_code == 201
分离测试逻辑与数据:将测试数据存储在外部文件(JSON/YAML)中。
统一断言处理:封装公共断言方法(如检查响应格式)。
异常处理:捕获预期异常并验证错误码。
日志记录:在 utils/logger.py
中集成日志,记录请求和响应详情。
持续集成:通过 GitHub Actions/Jenkins 定时执行测试。
import logging from utils.logger import setup_logger setup_logger() # 初始化日志 logger = logging.getLogger(__name__) def test_complex_flow(client): try: # 步骤1:创建用户 user_data = {"name": "Charlie"} create_res = client.post("/users", data=user_data) assert create_res.status_code == 201 user_id = create_res.json()["id"] logger.info(f"Created user {user_id}") # 步骤2:查询用户 get_res = client.get(f"/users/{user_id}") assert get_res.json()["name"] == "Charlie" except Exception as e: logger.error(f"Test failed: {str(e)}") raise # 标记测试失败
通过以上设计,你可以快速搭建一个 高可维护性、可扩展的接口自动化测试框架。