# User API 测试代码重构优化 **日期**: 2026-01-28 **类型**: Refactor **影响范围**: User API 集成测试 ## 优化目标 提升测试代码的可维护性、可读性和 DRY(Don't Repeat Yourself)原则。 ## 优化内容 ### 1. 提取测试常量 将硬编码的测试数据提取为常量,便于统一管理和修改: ```python # ==================== 测试常量 ==================== TEST_PHONE = "15980906230" TEST_COUNTRY_CODE = "+86" TEST_VERIFICATION_CODE = "6666" # 测试环境的万能验证码 ``` **优势**: - 避免魔法数字和字符串 - 统一修改测试数据 - 提高代码可读性 ### 2. 封装响应断言函数 创建 `assert_success()` 函数,减少重复的响应格式断言: ```python 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 解析失败导致测试崩溃: ```python 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,避免每个测试重复登录: ```python @pytest_asyncio.fixture async def auth(async_client: AsyncClient) -> dict: """认证 fixture:提供已登录的用户信息""" return await login_and_get_token(async_client) ``` **优势**: - 减少重复的登录代码 - 测试代码更简洁 - 保持测试独立性(function 级别 fixture) ### 5. 更新所有测试方法 将所有需要认证的测试方法改为使用 `auth` fixture: ```python # ❌ 优化前:每个测试都要登录 @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 集成测试通过: ```bash 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,确保测试独立 ## 相关文档 - [测试规范文档](.claude/skills/jointo-tech-stack/references/testing.md) - [pytest fixtures 文档](https://docs.pytest.org/en/stable/fixture.html)