Python数据API响应断言怎么编写

wen python案例 16

本文目录导读:

Python数据API响应断言怎么编写

  1. 基础断言方法
  2. 使用unittest框架
  3. 使用pytest框架(推荐)
  4. 高级断言技巧
  5. 实际项目中的断言工具类

我来详细介绍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
        })
  1. 分离测试数据和断言逻辑
  2. 使用fixture管理测试准备和清理
  3. 参数化测试覆盖不同场景
  4. 分组测试用例,便于管理和报告
  5. 添加清晰的断言错误信息
  6. 合理使用超时和重试机制
  7. 测试数据和代码进行版本控制

这些方法可以根据具体项目需求进行调整和组合使用。

抱歉,评论功能暂时关闭!