本文目录导读:

我来详细介绍Python中数据API响应的断言编写方法:
基础断言方法
使用requests库 + 内置assert
import requests
import json
def test_api_response():
# 发送请求
response = requests.get("https://api.example.com/users/1")
# 状态码断言
assert response.status_code == 200, f"状态码错误:{response.status_code}"
# 获取JSON响应
data = response.json()
# 基本字段断言
assert "id" in data, "响应中缺少id字段"
assert "name" in data, "响应中缺少name字段"
assert "email" in data, "响应中缺少email字段"
# 值类型断言
assert isinstance(data["id"], int), "id应该是整数类型"
assert isinstance(data["name"], str), "name应该是字符串类型"
# 具体值断言
assert data["name"] == "张三", f"名称不符,期望张三,实际{data['name']}"
使用unittest框架
import unittest
import requests
import json
class TestUserAPI(unittest.TestCase):
def setUp(self):
self.base_url = "https://api.example.com"
def test_get_user(self):
response = requests.get(f"{self.base_url}/users/1")
# 状态码断言
self.assertEqual(response.status_code, 200)
data = response.json()
# 字段存在断言
self.assertIn("id", data)
self.assertIn("name", data)
# 字段值断言
self.assertEqual(data["id"], 1)
self.assertIsNotNone(data["name"])
self.assertTrue(len(data["name"]) > 0)
def test_create_user(self):
user_data = {
"name": "李四",
"email": "lisi@example.com",
"age": 25
}
response = requests.post(
f"{self.base_url}/users",
json=user_data
)
self.assertEqual(response.status_code, 201)
data = response.json()
# 验证返回的新用户数据
self.assertEqual(data["name"], user_data["name"])
self.assertEqual(data["email"], user_data["email"])
self.assertIn("id", data) # 系统应该生成ID
def test_get_nonexistent_user(self):
response = requests.get(f"{self.base_url}/users/99999")
self.assertEqual(response.status_code, 404)
data = response.json()
self.assertIn("error", data)
self.assertEqual(data["error"], "用户不存在")
if __name__ == "__main__":
unittest.main()
使用pytest框架(推荐)
import pytest
import requests
import json
# fixture提供测试数据
@pytest.fixture
def api_client():
return "https://api.example.com"
@pytest.fixture
def sample_user_data():
return {
"name": "王五",
"email": "wangwu@example.com",
"age": 30
}
def test_get_user_success(api_client):
"""测试获取用户成功"""
response = requests.get(f"{api_client}/users/1")
# 状态码断言
assert response.status_code == 200
data = response.json()
# 综合断言
assert all(key in data for key in ["id", "name", "email", "age"])
assert isinstance(data["id"], int)
assert isinstance(data["name"], str)
assert data["id"] == 1
def test_create_user(api_client, sample_user_data):
"""测试创建用户"""
response = requests.post(
f"{api_client}/users",
json=sample_user_data
)
assert response.status_code == 201
assert response.headers["Content-Type"] == "application/json"
created_user = response.json()
assert created_user["name"] == sample_user_data["name"]
assert created_user["email"] == sample_user_data["email"]
assert "id" in created_user
def test_update_user(api_client):
"""测试更新用户"""
update_data = {"name": "赵六", "age": 35}
response = requests.put(
f"{api_client}/users/1",
json=update_data
)
assert response.status_code == 200
updated_user = response.json()
assert updated_user["name"] == update_data["name"]
assert updated_user["age"] == update_data["age"]
def test_delete_user(api_client):
"""测试删除用户"""
response = requests.delete(f"{api_client}/users/1")
assert response.status_code == 204
# 204无内容响应,不应该有body
assert len(response.content) == 0
@pytest.mark.parametrize("user_id,expected_status", [
(1, 200),
(-1, 400),
(99999, 404),
])
def test_get_user_parameterized(api_client, user_id, expected_status):
"""参数化测试不同用户ID"""
response = requests.get(f"{api_client}/users/{user_id}")
assert response.status_code == expected_status
高级断言技巧
import requests
from datetime import datetime
def advanced_assertions():
response = requests.get("https://api.example.com/users/1")
data = response.json()
# 1. 正则表达式匹配
import re
assert re.match(r"^\w+@\w+\.\w+$", data["email"]), "邮箱格式不正确"
# 2. 数值范围断言
assert 0 <= data["age"] <= 150, f"年龄超出范围:{data['age']}"
# 3. 日期格式断言
try:
datetime.fromisoformat(data["created_at"])
except ValueError:
assert False, "日期格式不正确"
# 4. 列表断言
assert len(data.get("tags", [])) > 0, "用户至少需要一个标签"
assert all(isinstance(tag, str) for tag in data["tags"]), "标签应为字符串"
# 5. 嵌套JSON断言
address = data.get("address", {})
assert "city" in address and "province" in address
# 6. 响应时间断言
assert response.elapsed.total_seconds() < 5, "响应过慢"
# 7. 响应头断言
assert response.headers["Content-Type"] == "application/json"
# 使用第三方库:jsonschema进行JSON Schema验证
from jsonschema import validate, ValidationError
def test_with_json_schema():
schema = {
"type": "object",
"required": ["id", "name", "email"],
"properties": {
"id": {"type": "integer", "minimum": 1},
"name": {"type": "string", "minLength": 1},
"email": {"type": "string", "format": "email"},
"age": {"type": "integer", "minimum": 0, "maximum": 150},
"address": {
"type": "object",
"properties": {
"city": {"type": "string"},
"province": {"type": "string"}
}
}
}
}
response = requests.get("https://api.example.com/users/1")
data = response.json()
try:
validate(instance=data, schema=schema)
assert True
except ValidationError as e:
assert False, f"JSON Schema验证失败:{e.message}"
实际项目中的断言工具类
class APIResponseAssertions:
@staticmethod
def assert_status_code(response, expected_code=200):
assert response.status_code == expected_code, \
f"期望状态码{expected_code},实际{response.status_code}"
@staticmethod
def assert_required_fields(data, required_fields):
missing_fields = [field for field in required_fields if field not in data]
assert not missing_fields, f"缺少必要字段:{missing_fields}"
@staticmethod
def assert_field_types(data, type_map):
for field, expected_type in type_map.items():
assert field in data, f"缺少字段:{field}"
assert isinstance(data[field], expected_type), \
f"字段{field}类型错误,期望{expected_type},实际{type(data[field])}"
@staticmethod
def assert_response_time(response, max_seconds=3):
assert response.elapsed.total_seconds() < max_seconds, \
f"响应过慢:{response.elapsed.total_seconds()}秒"
@staticmethod
def assert_pagination(response, expected_page=None, expected_per_page=None):
data = response.json()
assert "page" in data
assert "per_page" in data
assert "total" in data
assert "total_pages" in data
if expected_page:
assert data["page"] == expected_page
if expected_per_page:
assert data["per_page"] == expected_per_page
# 使用示例
def test_complex_api():
assertions = APIResponseAssertions()
response = requests.get("https://api.example.com/users?page=1&per_page=10")
assertions.assert_status_code(response, 200)
assertions.assert_response_time(response, 5)
assertions.assert_pagination(response, expected_page=1, expected_per_page=10)
data = response.json()
assertions.assert_required_fields(data, ["users", "page", "per_page", "total"])
for user in data["users"]:
assertions.assert_required_fields(user, ["id", "name", "email"])
assertions.assert_field_types(user, {
"id": int,
"name": str,
"email": str
})
- 分离测试数据和断言逻辑
- 使用fixture管理测试准备和清理
- 参数化测试覆盖不同场景
- 分组测试用例,便于管理和报告
- 添加清晰的断言错误信息
- 合理使用超时和重试机制
- 测试数据和代码进行版本控制
这些方法可以根据具体项目需求进行调整和组合使用。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播