You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

4.7 KiB

User API 测试代码重构优化

日期: 2026-01-28
类型: Refactor
影响范围: User API 集成测试

优化目标

提升测试代码的可维护性、可读性和 DRY(Don't Repeat Yourself)原则。

优化内容

1. 提取测试常量

将硬编码的测试数据提取为常量,便于统一管理和修改:

# ==================== 测试常量 ====================

TEST_PHONE = "15980906230"
TEST_COUNTRY_CODE = "+86"
TEST_VERIFICATION_CODE = "6666"  # 测试环境的万能验证码

优势

  • 避免魔法数字和字符串
  • 统一修改测试数据
  • 提高代码可读性

2. 封装响应断言函数

创建 assert_success() 函数,减少重复的响应格式断言:

def assert_success(data: dict, message: str = "请求应该成功") -> None:
    """断言 API 响应成功"""
    assert data.get("code") == 200 or data.get("success") is True, f"{message}: {data}"

优势

  • 减少重复代码
  • 统一断言逻辑
  • 提供更清晰的错误信息

3. 添加安全的 JSON 解析

创建 safe_json() 函数,避免 JSON 解析失败导致测试崩溃:

def safe_json(response) -> dict:
    """安全地解析 JSON 响应"""
    if response.headers.get("content-type", "").startswith("application/json"):
        try:
            return response.json()
        except Exception:
            return {}
    return {}

优势

  • 处理非 JSON 响应(如 500 错误返回 HTML)
  • 避免测试因解析错误而崩溃
  • 提供更好的错误处理

4. 使用 Fixture 提供认证信息

创建 auth fixture,避免每个测试重复登录:

@pytest_asyncio.fixture
async def auth(async_client: AsyncClient) -> dict:
    """认证 fixture:提供已登录的用户信息"""
    return await login_and_get_token(async_client)

优势

  • 减少重复的登录代码
  • 测试代码更简洁
  • 保持测试独立性(function 级别 fixture)

5. 更新所有测试方法

将所有需要认证的测试方法改为使用 auth fixture:

# ❌ 优化前:每个测试都要登录
@pytest.mark.asyncio
async def test_get_current_user(self, async_client: AsyncClient):
    auth = await login_and_get_token(async_client)
    response = await async_client.get(
        "/api/v1/users/me",
        headers={"Authorization": f"Bearer {auth['access_token']}"}
    )
    # ...

# ✅ 优化后:使用 fixture
@pytest.mark.asyncio
async def test_get_current_user(self, async_client: AsyncClient, auth: dict):
    response = await async_client.get(
        "/api/v1/users/me",
        headers={"Authorization": f"Bearer {auth['access_token']}"}
    )
    # ...

修改文件

  • server/tests/integration/test_user_api.py - 重构测试代码

测试结果

所有 11 个 User API 集成测试通过:

tests/integration/test_user_api.py::TestUserAPI::test_health_check PASSED
tests/integration/test_user_api.py::TestUserAPI::test_send_sms_verification_code PASSED
tests/integration/test_user_api.py::TestUserAPI::test_phone_login PASSED
tests/integration/test_user_api.py::TestUserAPI::test_get_current_user PASSED
tests/integration/test_user_api.py::TestUserAPI::test_update_user_info PASSED
tests/integration/test_user_api.py::TestUserAPI::test_get_credits_info PASSED
tests/integration/test_user_api.py::TestUserAPI::test_bind_email PASSED
tests/integration/test_user_api.py::TestUserAPI::test_logout PASSED
tests/integration/test_user_api.py::TestUserAPIEdgeCases::test_login_with_invalid_code PASSED
tests/integration/test_user_api.py::TestUserAPIEdgeCases::test_access_protected_route_without_token PASSED
tests/integration/test_user_api.py::TestUserAPIEdgeCases::test_access_protected_route_with_invalid_token PASSED

代码质量提升

优化前

  • 硬编码的测试数据散落在各处
  • 重复的响应断言代码(assert data.get("code") == 200 or data.get("success") == True
  • 每个测试都要调用 login_and_get_token()
  • 缺少 JSON 解析的异常处理

优化后

  • 测试常量统一管理
  • 封装的断言函数,代码更简洁
  • 使用 fixture 提供认证信息
  • 安全的 JSON 解析,避免测试崩溃
  • 代码行数减少约 20%
  • 可维护性显著提升

最佳实践

  1. DRY 原则:提取重复代码为函数或 fixture
  2. 常量管理:将硬编码的测试数据提取为常量
  3. 异常处理:添加安全的 JSON 解析,避免测试崩溃
  4. Fixture 使用:使用 fixture 提供共享的测试资源
  5. 测试独立性:保持 function 级别的 fixture,确保测试独立

相关文档