E2E 测试文档

本文档介绍 MBE 项目的端到端(E2E)测试实现和使用方法。

概述

E2E 测试覆盖完整的用户流程,从用户注册到 API 调用,再到错误处理。这些测试确保整个系统在真实场景下能够正常工作。

测试文件结构

tests/e2e/
├── __init__.py
├── test_user_e2e_workflow.py      # 完整用户流程测试
├── test_api_e2e_workflow.py       # API 调用完整流程测试
└── test_error_handling_e2e.py      # 错误处理流程测试

测试覆盖范围

1. 用户端到端流程 (test_user_e2e_workflow.py)

测试场景

  1. 完整用户流程 (test_complete_user_workflow)

    • 用户注册(在 fixture 中完成)
    • 用户登录
    • 获取用户信息
    • 获取 Token 余额
    • 使用 API(调用专家)
    • 查看使用统计
    • 刷新 Token
  2. Token 购买和使用流程 (test_token_purchase_and_usage_workflow)

    • 查看当前余额
    • 创建 Token 购买订单
    • 查看订单状态
    • 使用 Token
    • 查看使用后的余额
  3. 订阅管理流程 (test_subscription_management_workflow)

    • 查看当前订阅
    • 升级订阅(如果支持)
    • 查看订阅详情
    • 查看订阅使用统计
  4. 错误处理流程 (test_error_handling_workflow)

    • 使用错误密码登录
    • 使用无效 Token 访问受保护端点
    • 访问不存在的资源
    • 使用无效参数调用 API
  5. API 调用完整流程 (test_api_call_complete_workflow)

    • 获取 API Key(如果支持)
    • 使用 API Key 调用 API
    • 查看 API 调用历史
    • 查看 API 使用统计
  6. 设备绑定流程 (test_device_binding_workflow)

    • 绑定设备
    • 查看设备列表
    • 解绑设备(如果支持)
  7. 用户资料更新流程 (test_user_profile_update_workflow)

    • 获取当前用户信息
    • 更新用户信息
    • 验证更新成功

2. API 调用完整流程 (test_api_e2e_workflow.py)

测试场景

  1. API 认证流程 (test_api_authentication_flow)

    • 未认证访问受保护端点(应失败)
    • 注册并获取 Token
    • 使用 Token 访问受保护端点(应成功)
    • Token 过期处理(如果可能)
  2. API 速率限制 (test_api_rate_limiting)

    • 快速连续调用 API
    • 验证速率限制生效
    • 等待后重试
  3. API 错误响应 (test_api_error_responses)

    • 400 Bad Request(无效参数)
    • 404 Not Found(资源不存在)
    • 422 Unprocessable Entity(验证错误)
  4. API 响应格式 (test_api_response_format)

    • 成功响应格式
    • 错误响应格式
    • 分页响应格式(如果适用)
  5. API 并发请求 (test_api_concurrent_requests)

    • 同时发送多个请求
    • 验证所有请求都能正确处理
  6. API CORS 头 (test_api_cors_headers)

    • OPTIONS 预检请求
    • 验证 CORS 头存在

3. 错误处理流程 (test_error_handling_e2e.py)

测试场景

  1. 认证错误 (test_authentication_errors)

    • 无效 Token
    • 过期 Token(如果可能)
    • 缺失 Token
    • 错误格式的 Token
  2. 验证错误 (test_validation_errors)

    • 无效邮箱格式
    • 密码太短
    • 缺失必填字段
    • 类型错误
  3. 404 错误 (test_not_found_errors)

    • 不存在的用户
    • 不存在的资源
    • 不存在的端点
  4. 重复资源错误 (test_duplicate_resource_errors)

    • 重复邮箱注册
    • 重复设备绑定(如果适用)
  5. 权限错误 (test_permission_errors)

    • 普通用户访问管理员端点
    • 未授权访问受保护资源
  6. 速率限制错误 (test_rate_limit_errors)

    • 快速连续请求
    • 验证 429 响应
    • 验证重试机制
  7. 格式错误请求 (test_malformed_request_errors)

    • 无效 JSON
    • 缺失 Content-Type
    • 无效的 HTTP 方法
  8. 错误响应格式 (test_error_response_format)

    • 所有错误都应该有 detail 或 message 字段
    • 错误响应格式应该一致

运行测试

运行所有 E2E 测试

# 运行所有 E2E 测试
pytest tests/e2e/ -v -m e2e

# 运行所有 E2E 测试(包括集成测试标记)
pytest tests/e2e/ -v -m "e2e or integration"

运行特定测试文件

# 运行用户流程测试
pytest tests/e2e/test_user_e2e_workflow.py -v

# 运行 API 流程测试
pytest tests/e2e/test_api_e2e_workflow.py -v

# 运行错误处理测试
pytest tests/e2e/test_error_handling_e2e.py -v

运行特定测试场景

# 运行完整用户流程测试
pytest tests/e2e/test_user_e2e_workflow.py::TestUserE2EWorkflow::test_complete_user_workflow -v

# 运行 Token 购买和使用流程测试
pytest tests/e2e/test_user_e2e_workflow.py::TestUserE2EWorkflow::test_token_purchase_and_usage_workflow -v

测试依赖

E2E 测试需要以下依赖:

  • pytest - 测试框架
  • pytest-asyncio - 异步测试支持
  • httpx - HTTP 测试客户端

这些依赖已在 tests/requirements.txt 中定义。

测试 Fixtures

registered_user

自动注册用户并返回认证信息:

@pytest.fixture
async def registered_user(client, test_email, test_password):
    # 注册用户并返回认证信息
    return {
        "user_id": ...,
        "email": ...,
        "access_token": ...,
        "refresh_token": ...
    }

authenticated_client

创建已认证的测试客户端:

@pytest.fixture
async def authenticated_client(client):
    # 注册用户并设置认证头
    client.headers.update({"Authorization": f"Bearer {access_token}"})
    yield client

测试数据管理

自动清理

测试使用 clean_db fixture 自动清理测试数据:

  • 测试用户(email 以 test@ 开头)
  • 测试设备(device_id 以 test- 开头)
  • 关联的 Token 余额和订阅数据

唯一测试数据

每个测试使用时间戳生成唯一的测试数据:

test_email = f"e2e-test-{int(time.time() * 1000)}@mbe-test.com"

这确保测试之间不会相互干扰。

跳过条件

某些测试可能会跳过,如果:

  1. 功能不可用:如果某个功能端点不存在或不可用,测试会跳过
  2. 服务不可用:如果依赖的服务(如专家服务)不可用,测试会跳过
  3. 环境限制:如果测试环境不支持某些功能,测试会跳过

跳过时会显示原因:

pytest.skip(f"专家服务不可用: {e}")

最佳实践

1. 测试隔离

每个测试都是独立的,不依赖其他测试的状态:

  • 使用唯一的测试数据(时间戳)
  • 自动清理测试数据
  • 不共享测试状态

2. 错误处理

测试应该验证错误情况:

  • 无效输入应该返回适当的错误码
  • 错误响应应该有正确的格式
  • 错误消息应该清晰明确

3. 可读性

测试应该清晰易懂:

  • 使用描述性的测试名称
  • 添加注释说明测试目的
  • 使用有意义的变量名

4. 性能

E2E 测试可能较慢,应该:

  • 避免不必要的等待
  • 使用并发测试(如果可能)
  • 标记慢速测试(@pytest.mark.slow

持续集成

E2E 测试应该在 CI/CD 流程中运行:

# .github/workflows/test.yml
- name: Run E2E Tests
  run: |
    pytest tests/e2e/ -v -m e2e

故障排查

常见问题

  1. 数据库连接错误

    • 确保数据库服务正在运行
    • 检查数据库连接配置
  2. Redis 连接错误

    • 确保 Redis 服务正在运行
    • 检查 Redis 连接配置
  3. 测试超时

    • 增加测试超时时间
    • 检查是否有长时间运行的测试
  4. 事件循环错误

    • 确保使用 pytest-asyncioauto 模式
    • 检查 fixture 的事件循环配置

扩展测试

添加新的 E2E 测试

  1. tests/e2e/ 目录下创建新的测试文件
  2. 使用 @pytest.mark.e2e 标记测试类
  3. 使用 @pytest.mark.integration 标记需要集成测试的测试
  4. 使用 @pytest.mark.asyncio 标记异步测试

示例:

@pytest.mark.e2e
@pytest.mark.integration
class TestNewFeatureE2E:
    @pytest.mark.asyncio
    async def test_new_feature_workflow(self, client: AsyncClient):
        # 测试实现
        pass

相关文档