以下是一个基于 Python 的接口自动化框架示例,结合 pytest + requests + Allure 实现,包含完整的项目结构、数据驱动、断言机制和报告生成功能。
1. 项目目录结构
api_test_project/
├── config/ # 配置文件
│ └── config.yaml # 环境配置(测试/生产环境URL等)
├── test_cases/ # 测试用例
│ ├── __init__.py
│ ├── test_login.py # 登录接口测试
│ └── test_user.py # 用户管理接口测试
├── utils/ # 工具类
│ ├── __init__.py
│ ├── request_util.py # 封装requests请求
│ └── assert_util.py # 自定义断言方法
├── data/ # 测试数据
│ ├── login_data.json # 登录接口参数化数据
│ └── user_data.csv
├── conftest.py # pytest全局fixture
├── requirements.txt # 依赖库
└── pytest.ini # pytest配置文件
2. 核心代码示例
(1) 封装请求工具类 utils/request_util.py
import requests
import yaml
from pathlib import Path
class RequestUtil:
def __init__(self):
# 读取配置文件(YAML格式)
config_path = Path(__file__).parent.parent / "config" / "config.yaml"
with open(config_path, 'r') as f:
self.config = yaml.safe_load(f)
self.base_url = self.config['base_url']
self.session = requests.Session()
def send_request(self, method, endpoint, params=None, data=None, json=None, headers=None):
url = f"{self.base_url}{endpoint}"
# 发送请求
response = self.session.request(
method=method.upper(),
url=url,
params=params,
data=data,
json=json,
headers=headers
)
return response
# 示例:全局请求对象
request_util = RequestUtil()
(2) 测试用例 test_cases/test_login.py
import pytest
import allure
from utils.request_util import request_util
from utils.assert_util import assert_status_code, assert_json_key
@allure.feature("登录模块")
class TestLogin:
@allure.story("用户登录")
@pytest.mark.parametrize("case_data", [
{"username": "admin", "password": "123456", "expected_code": 200},
{"username": "invalid", "password": "wrong", "expected_code": 401}
])
def test_login(self, case_data):
# 发送POST请求
endpoint = "/api/login"
payload = {
"username": case_data["username"],
"password": case_data["password"]
}
response = request_util.send_request("POST", endpoint, json=payload)
# 断言状态码和响应体
assert_status_code(response, case_data["expected_code"])
if response.status_code == 200:
assert_json_key(response, "token") # 验证返回token字段
(3) 自定义断言工具 utils/assert_util.py
def assert_status_code(response, expected_code):
assert response.status_code == expected_code, \
f"状态码不符!预期: {expected_code}, 实际: {response.status_code}"
def assert_json_key(response, key):
json_data = response.json()
assert key in json_data, f"响应中缺少关键字段: {key}"
return json_data[key] # 返回字段值供后续使用(如获取token)
3. 数据驱动示例
(1) 从JSON文件读取数据 data/login_data.json
[
{
"username": "test_user",
"password": "pass123",
"expected_code": 200
},
{
"username": "locked_user",
"password": "wrong_pass",
"expected_code": 403
}
]
(2) 在测试用例中加载JSON数据
import json
from pathlib import Path
def load_json_data(file_name):
data_path = Path(__file__).parent.parent / "data" / file_name
with open(data_path, 'r') as f:
return json.load(f)
@pytest.mark.parametrize("case_data", load_json_data("login_data.json"))
def test_login_with_json_data(case_data):
# 测试逻辑同上
pass
4. 配置文件 config/config.yaml
# 测试环境配置
base_url: "https://test-api.example.com"
headers:
Content-Type: "application/json"
# 生产环境配置(通过环境变量切换)
# base_url: "https://prod-api.example.com"
5. 运行测试并生成报告
(1) 安装依赖 requirements.txt
pytest==7.4.0
requests==2.31.0
PyYAML==6.0.1
allure-pytest==2.13.2
pytest-html==4.1.1
(2) 执行测试命令
# 运行所有测试并生成Allure报告
pytest --alluredir=./results --clean-alluredir
allure serve ./results
# 或生成HTML报告
pytest --html=report.html
6. 高级功能扩展
(1) 接口依赖处理(获取Token)
# 在conftest.py中定义全局fixture
@pytest.fixture(scope="session")
def auth_token():
payload = {"username": "admin", "password": "123456"}
response = request_util.send_request("POST", "/api/login", json=payload)
token = response.json()["token"]
return token
# 在测试用例中使用token
def test_user_info(auth_token):
headers = {"Authorization": f"Bearer {auth_token}"}
response = request_util.send_request("GET", "/api/user/1", headers=headers)
(2) 数据库校验
# 添加数据库工具类(如使用SQLAlchemy)
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():
# 调用接口创建用户
response = request_util.send_request("POST", "/api/users", json={"name": "Alice"})
user_id = response.json()["id"]
# 验证数据库
db_util = DBUtil("mysql://user:pass@localhost/db")
user = db_util.query_user(user_id)
assert user["name"] == "Alice"
7. 框架选择建议
-
轻量级需求:直接使用
pytest + requests(如上述示例)。 -
企业级复杂场景:选择
HttpRunner或Tavern,它们提供更丰富的内置功能:- HttpRunner:支持YAML/JSON用例编写、性能测试、CI/CD集成。
- test: name: 登录接口测试 request: url: /api/login method: POST json: username: admin password: 123456 validate: - eq: [status_code, 200] - contains: $.token
总结
该框架具备以下特点:
- 模块化设计:分离请求封装、断言、数据管理。
- 易于扩展:支持数据库校验、Mock服务、分布式执行。
- 报告友好:Allure报告展示详细测试结果。
- 适合团队协作:标准化项目结构,方便多人维护。
可根据实际需求调整技术栈(如用 unittest 替代 pytest,或用 FastAPI 搭建Mock服务)。