geo/.qoder/repowiki/zh/content/测试策略/集成测试.md

365 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 集成测试
<cite>
**本文引用的文件**
- [tests/conftest.py](file://tests/conftest.py)
- [backend/app/main.py](file://backend/app/main.py)
- [backend/app/database.py](file://backend/app/database.py)
- [backend/app/config.py](file://backend/app/config.py)
- [docker-compose.yml](file://docker-compose.yml)
- [tests/test_auth.py](file://tests/test_auth.py)
- [tests/test_queries.py](file://tests/test_queries.py)
- [tests/test_citations.py](file://tests/test_citations.py)
- [backend/app/api/deps.py](file://backend/app/api/deps.py)
- [backend/app/api/auth.py](file://backend/app/api/auth.py)
- [backend/app/api/queries.py](file://backend/app/api/queries.py)
- [backend/app/api/citations.py](file://backend/app/api/citations.py)
- [backend/app/workers/scheduler.py](file://backend/app/workers/scheduler.py)
- [backend/app/services/auth.py](file://backend/app/services/auth.py)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖分析](#依赖分析)
7. [性能考虑](#性能考虑)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本文件面向GEO项目的集成测试系统性阐述端到端测试的实现方法与最佳实践覆盖以下方面
- FastAPI应用测试通过ASGI传输层在内存中启动应用使用异步HTTP客户端进行端到端请求验证。
- 数据库连接测试基于异步SQLAlchemy引擎与会话管理确保依赖注入与数据库交互正确。
- 外部服务集成测试通过依赖注入覆盖与模拟patch实现对外部平台如wenxin、kimi的模拟调用。
- 测试环境配置:测试数据库、异步客户端、依赖注入覆盖与后台调度器的处理策略。
- 完整用户工作流:从认证到查询创建、执行到结果返回的端到端流程验证。
- 数据库事务与测试数据隔离:通过依赖注入覆盖与会话生命周期管理保障隔离性。
- 性能与负载测试:提供可扩展的测试方法与建议。
## 项目结构
GEO采用前后端分离架构后端使用FastAPI + SQLAlchemy异步ORM测试位于tests目录通过pytest与pytest-asyncio驱动异步测试。数据库与缓存服务通过Docker Compose编排便于本地与CI环境一致化。
```mermaid
graph TB
subgraph "测试环境"
TC["测试客户端<br/>AsyncClient(ASGI)"]
CFG["测试配置<br/>Settings(.env)"]
DC["Docker Compose<br/>db, redis, backend, frontend"]
end
subgraph "后端"
APP["FastAPI 应用<br/>app.main"]
DEPS["依赖注入<br/>api.deps"]
AUTH["认证路由<br/>api.auth"]
QUERIES["查询路由<br/>api.queries"]
CITATIONS["引用路由<br/>api.citations"]
SCHED["调度器<br/>workers.scheduler"]
DB["数据库引擎/会话<br/>database.py"]
end
DC --> APP
CFG --> APP
TC --> APP
APP --> AUTH
APP --> QUERIES
APP --> CITATIONS
APP --> SCHED
AUTH --> DB
QUERIES --> DB
CITATIONS --> DB
DEPS --> DB
```
图表来源
- [backend/app/main.py:1-48](file://backend/app/main.py#L1-L48)
- [backend/app/api/deps.py:1-43](file://backend/app/api/deps.py#L1-L43)
- [backend/app/api/auth.py:1-43](file://backend/app/api/auth.py#L1-L43)
- [backend/app/api/queries.py:1-86](file://backend/app/api/queries.py#L1-L86)
- [backend/app/api/citations.py:1-78](file://backend/app/api/citations.py#L1-L78)
- [backend/app/database.py:1-29](file://backend/app/database.py#L1-L29)
- [backend/app/workers/scheduler.py:1-95](file://backend/app/workers/scheduler.py#L1-L95)
- [docker-compose.yml:1-71](file://docker-compose.yml#L1-L71)
章节来源
- [backend/app/main.py:1-48](file://backend/app/main.py#L1-L48)
- [docker-compose.yml:1-71](file://docker-compose.yml#L1-L71)
## 核心组件
- 异步HTTP客户端与ASGI传输层通过ASGITransport在内存中启动FastAPI应用避免真实网络开销提升测试速度与稳定性。
- 依赖注入覆盖使用app.dependency_overrides在测试中替换真实依赖如认证用户以模拟不同业务场景。
- 认证与令牌通过create_access_token生成JWT配合OAuth2PasswordBearer在路由中校验令牌。
- 数据库引擎与会话异步SQLAlchemy引擎与会话工厂确保测试中数据库交互的可控性与隔离性。
- 后台调度器QueryScheduler负责周期性检查并触发查询任务测试中通过mock屏蔽真实调度防止后台任务干扰测试。
章节来源
- [tests/conftest.py:19-71](file://tests/conftest.py#L19-L71)
- [backend/app/api/deps.py:16-43](file://backend/app/api/deps.py#L16-L43)
- [backend/app/services/auth.py:24-34](file://backend/app/services/auth.py#L24-L34)
- [backend/app/database.py:6-29](file://backend/app/database.py#L6-L29)
- [backend/app/workers/scheduler.py:25-95](file://backend/app/workers/scheduler.py#L25-L95)
## 架构总览
下图展示测试视角下的端到端调用链路从异步客户端发起请求经由FastAPI路由、依赖注入、服务层最终访问数据库或外部平台通过模拟
```mermaid
sequenceDiagram
participant Test as "测试客户端"
participant App as "FastAPI 应用"
participant Dep as "依赖注入<br/>get_current_user"
participant Auth as "认证路由<br/>/api/v1/auth/*"
participant Queries as "查询路由<br/>/api/v1/queries/*"
participant Citations as "引用路由<br/>/api/v1/citations/*"
participant DB as "数据库引擎/会话"
Test->>App : "POST /api/v1/auth/register"
App->>Dep : "解析令牌/校验用户"
App->>Auth : "注册逻辑"
Auth->>DB : "写入用户"
DB-->>Auth : "提交成功"
Auth-->>Test : "201 用户信息"
Test->>App : "POST /api/v1/auth/login"
App->>Auth : "登录校验"
Auth-->>Test : "200 {access_token}"
Test->>App : "POST /api/v1/queries/"
App->>Dep : "校验令牌并解析用户"
App->>Queries : "创建查询"
Queries->>DB : "插入查询记录"
DB-->>Queries : "提交成功"
Queries-->>Test : "201 查询详情"
Test->>App : "GET /api/v1/citations/?query_id=..."
App->>Dep : "校验令牌并解析用户"
App->>Citations : "查询引用数据"
Citations->>DB : "读取引用记录"
DB-->>Citations : "返回数据"
Citations-->>Test : "200 引用列表"
```
图表来源
- [tests/test_auth.py:25-104](file://tests/test_auth.py#L25-L104)
- [tests/test_queries.py:29-154](file://tests/test_queries.py#L29-L154)
- [tests/test_citations.py:23-93](file://tests/test_citations.py#L23-L93)
- [backend/app/api/auth.py:13-43](file://backend/app/api/auth.py#L13-L43)
- [backend/app/api/queries.py:15-86](file://backend/app/api/queries.py#L15-L86)
- [backend/app/api/citations.py:25-78](file://backend/app/api/citations.py#L25-L78)
- [backend/app/api/deps.py:16-43](file://backend/app/api/deps.py#L16-L43)
- [backend/app/database.py:23-29](file://backend/app/database.py#L23-L29)
## 详细组件分析
### 测试环境与配置
- 测试数据库与外部服务通过Docker Compose启动PostgreSQL与Redis确保测试与生产环境一致数据库URL与Redis URL在配置类中定义便于在测试中覆盖。
- 异步客户端使用ASGITransport在内存中启动FastAPI应用避免网络抖动对测试的影响。
- 依赖注入覆盖在conftest中定义override_get_current_user使所有需要认证的路由在测试中自动获得模拟用户。
- 调度器屏蔽通过mock_scheduler在测试期间禁用真实调度器防止后台任务影响测试稳定性。
章节来源
- [docker-compose.yml:4-51](file://docker-compose.yml#L4-L51)
- [backend/app/config.py:7-14](file://backend/app/config.py#L7-L14)
- [tests/conftest.py:19-71](file://tests/conftest.py#L19-L71)
### 认证与用户工作流测试
- 注册与登录通过patch模拟注册与登录服务断言状态码与响应字段确保认证流程正确。
- 当前用户信息:在依赖注入覆盖下,调用/me接口返回当前用户信息。
- 未认证访问移除依赖注入覆盖后访问受保护路由应返回401。
```mermaid
sequenceDiagram
participant C as "测试客户端"
participant A as "认证路由"
participant S as "认证服务"
participant D as "数据库"
C->>A : "POST /api/v1/auth/register"
A->>S : "register_user()"
S->>D : "查询邮箱是否存在"
S->>D : "插入新用户"
D-->>S : "提交成功"
S-->>A : "返回用户"
A-->>C : "201 Created"
C->>A : "POST /api/v1/auth/login"
A->>S : "authenticate_user()"
S->>D : "查询用户并校验密码"
D-->>S : "返回用户"
S-->>A : "生成JWT"
A-->>C : "200 {access_token}"
```
图表来源
- [tests/test_auth.py:25-104](file://tests/test_auth.py#L25-L104)
- [backend/app/api/auth.py:13-43](file://backend/app/api/auth.py#L13-L43)
- [backend/app/services/auth.py:37-69](file://backend/app/services/auth.py#L37-L69)
章节来源
- [tests/test_auth.py:25-104](file://tests/test_auth.py#L25-L104)
- [backend/app/api/auth.py:13-43](file://backend/app/api/auth.py#L13-L43)
- [backend/app/services/auth.py:37-69](file://backend/app/services/auth.py#L37-L69)
### 查询管理端到端测试
- 创建查询:在依赖注入覆盖与令牌头下,调用创建接口,断言返回字段与状态码。
- 列表与详情通过patch模拟服务层返回值断言分页与字段一致性。
- 更新与删除:断言更新后的字段与删除后的状态码。
- 权限限制当超过配额时断言403错误与错误信息。
- 资源不存在断言404错误与错误信息。
```mermaid
sequenceDiagram
participant C as "测试客户端"
participant Q as "查询路由"
participant S as "查询服务"
participant D as "数据库"
C->>Q : "POST /api/v1/queries/"
Q->>S : "create_query()"
S->>D : "插入查询记录"
D-->>S : "提交成功"
S-->>Q : "返回查询"
Q-->>C : "201 Created"
C->>Q : "GET /api/v1/queries/?skip=&limit="
Q->>S : "get_queries()"
S->>D : "查询记录"
D-->>S : "返回列表"
S-->>Q : "返回分页"
Q-->>C : "200 OK"
C->>Q : "PUT /api/v1/queries/{id}"
Q->>S : "update_query()"
S->>D : "更新记录"
D-->>S : "提交成功"
S-->>Q : "返回更新后记录"
Q-->>C : "200 OK"
C->>Q : "DELETE /api/v1/queries/{id}"
Q->>S : "delete_query()"
S->>D : "删除记录"
D-->>S : "提交成功"
S-->>Q : "返回True"
Q-->>C : "204 No Content"
```
图表来源
- [tests/test_queries.py:29-154](file://tests/test_queries.py#L29-L154)
- [backend/app/api/queries.py:15-86](file://backend/app/api/queries.py#L15-L86)
章节来源
- [tests/test_queries.py:29-154](file://tests/test_queries.py#L29-L154)
- [backend/app/api/queries.py:15-86](file://backend/app/api/queries.py#L15-L86)
### 引用数据与统计导出测试
- 引用列表:断言分页、字段与过滤参数生效。
- 统计信息:断言总量、引用率、按平台分布与趋势数据。
- CSV导出断言内容类型、附件头与CSV内容片段。
```mermaid
sequenceDiagram
participant C as "测试客户端"
participant R as "引用路由"
participant RS as "引用服务"
participant D as "数据库"
C->>R : "GET /api/v1/citations/?query_id=&platform=&start_date=&end_date=&skip=&limit="
R->>RS : "get_citations()"
RS->>D : "查询引用记录"
D-->>RS : "返回列表"
RS-->>R : "返回分页"
R-->>C : "200 OK"
C->>R : "GET /api/v1/citations/stats?query_id="
R->>RS : "get_citation_stats()"
RS->>D : "聚合统计"
D-->>RS : "返回统计"
RS-->>R : "返回统计"
R-->>C : "200 OK"
C->>R : "GET /api/v1/reports/export/csv?query_id="
R->>RS : "export_citations_csv()"
RS-->>R : "返回CSV内容"
R-->>C : "200 OK, text/csv, attachment"
```
图表来源
- [tests/test_citations.py:23-93](file://tests/test_citations.py#L23-L93)
- [backend/app/api/citations.py:25-78](file://backend/app/api/citations.py#L25-L78)
章节来源
- [tests/test_citations.py:23-93](file://tests/test_citations.py#L23-L93)
- [backend/app/api/citations.py:25-78](file://backend/app/api/citations.py#L25-L78)
### 数据库事务管理与测试数据隔离
- 会话生命周期get_db提供异步会话生成与关闭确保每次请求在独立会话中执行避免跨请求污染。
- 依赖注入覆盖通过app.dependency_overrides在测试中替换get_current_user保证路由依赖始终可用且可控。
- 事务隔离测试中通过patch模拟服务层不直接写入真实数据若需真实写入应在测试事务中回滚或使用独立测试库。
```mermaid
flowchart TD
Start(["测试开始"]) --> Override["依赖注入覆盖<br/>get_current_user"]
Override --> Session["获取异步会话<br/>get_db()"]
Session --> Exec["执行路由/服务逻辑"]
Exec --> Commit{"提交/回滚?"}
Commit --> |提交| Close["关闭会话"]
Commit --> |回滚| Close
Close --> End(["测试结束"])
```
图表来源
- [tests/conftest.py:42-50](file://tests/conftest.py#L42-L50)
- [backend/app/database.py:23-29](file://backend/app/database.py#L23-L29)
章节来源
- [tests/conftest.py:42-50](file://tests/conftest.py#L42-L50)
- [backend/app/database.py:23-29](file://backend/app/database.py#L23-L29)
### 外部服务集成测试
- 平台模拟通过patch将平台调用替换为模拟实现断言触发查询任务与返回的任务信息。
- 调度器屏蔽在测试期间mock调度器避免真实后台任务执行确保测试确定性。
章节来源
- [tests/test_citations.py:75-93](file://tests/test_citations.py#L75-L93)
- [tests/conftest.py:19-26](file://tests/conftest.py#L19-L26)
## 依赖分析
- 应用生命周期FastAPI应用在lifespan中启动调度器并在关闭时优雅shutdown。
- 路由依赖:认证与查询/引用路由均依赖get_current_user与get_db形成清晰的依赖链。
- 服务层认证、查询、引用服务分别封装业务逻辑便于在测试中通过patch进行替换。
```mermaid
graph LR
APP["FastAPI 应用"] --> LIFE["lifespan 启停调度器"]
APP --> AUTH["认证路由"]
APP --> QUERIES["查询路由"]
APP --> CITATIONS["引用路由"]
AUTH --> DEPS["get_current_user"]
QUERIES --> DEPS
CITATIONS --> DEPS
DEPS --> DB["get_db/AsyncSession"]
```
图表来源
- [backend/app/main.py:13-22](file://backend/app/main.py#L13-L22)
- [backend/app/api/deps.py:16-43](file://backend/app/api/deps.py#L16-L43)
- [backend/app/database.py:23-29](file://backend/app/database.py#L23-L29)
章节来源
- [backend/app/main.py:13-22](file://backend/app/main.py#L13-L22)
- [backend/app/api/deps.py:16-43](file://backend/app/api/deps.py#L16-L43)
- [backend/app/database.py:23-29](file://backend/app/database.py#L23-L29)
## 性能考虑
- 内存测试使用ASGI传输层与异步客户端避免网络开销提升测试吞吐量。
- 调度器控制:在测试中禁用真实调度器,减少后台任务对测试性能的影响。
- 数据库隔离:通过独立测试库或事务回滚策略,避免并发测试导致的数据竞争。
- 负载测试建议:可在现有测试基础上扩展压力测试脚本,结合异步客户端批量发送请求,监控响应时间与错误率;注意在测试环境中使用独立数据库实例以避免影响生产数据。
## 故障排查指南
- 401未认证确认测试中是否正确设置依赖注入覆盖与Authorization头。
- 403权限不足检查配额限制逻辑与用户计划确保测试数据符合预期。
- 404资源不存在确认查询ID与用户归属确保服务层返回None时路由抛出404。
- 调度器干扰若出现不可预期的后台任务行为确认是否启用了mock_scheduler。
章节来源
- [tests/test_auth.py:88-104](file://tests/test_auth.py#L88-L104)
- [tests/test_queries.py:50-71](file://tests/test_queries.py#L50-L71)
- [tests/test_queries.py:127-154](file://tests/test_queries.py#L127-L154)
- [tests/conftest.py:19-26](file://tests/conftest.py#L19-L26)
## 结论
本文档提供了GEO项目集成测试的完整方法论与实施细节涵盖FastAPI应用测试、数据库连接、外部服务模拟、端到端用户工作流验证、事务与隔离策略以及性能与负载测试建议。通过依赖注入覆盖与异步客户端测试具备高可靠性与可维护性借助Docker Compose与配置类测试环境与生产环境保持一致便于持续集成与部署。
## 附录
- 建议在CI中增加
- 数据库迁移与初始化脚本的集成测试。
- Redis健康检查与连接超时重试策略验证。
- 前后端联调测试确保API与前端交互稳定。