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
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%
- 可维护性显著提升
最佳实践
- DRY 原则:提取重复代码为函数或 fixture
- 常量管理:将硬编码的测试数据提取为常量
- 异常处理:添加安全的 JSON 解析,避免测试崩溃
- Fixture 使用:使用 fixture 提供共享的测试资源
- 测试独立性:保持 function 级别的 fixture,确保测试独立