Files
nexus/Project/fonrey/TECH_STACK/测试规范.md
2026-04-27 16:26:34 +08:00

346 lines
9.4 KiB
Markdown
Raw 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.
> **For AI assistants**: Read this entire file before writing any test code. All decisions here are final. Do not suggest alternatives unless asked.
# Fonrey 测试规范TEST_SPEC
**版本**: 1.1
**项目**: Fonrey 房产经纪管理系统
**技术栈**: Django 4.x + django-tenants + PostgreSQL 16 + Redis + Celery + HTMX + Playwright
**关联文档**: `TECH_STACK/TECH_STACK.md``PRD/TASK.md`、各模块技术方案(登录/权限/房源/客源/楼盘/组织人事/系统管理)
**最后更新**: 2026-04-27
---
## 一、文档定位与边界
本文件定义项目统一测试标准:
1. 测试分层与覆盖率目标
2. 测试目录与夹具fixture约定
3. 多租户与 HTMX 场景测试规范
4. CI 执行基线与失败处理流程
5. AI 辅助开发的“测试随功能交付”硬约束
> 本文件不替代模块级测试设计。每个业务模块的案例细节以对应技术方案和 PRD AC 为准。
---
## 二、测试目标与覆盖基线
Fonrey 采用 AI 驱动迭代,测试是质量兜底。所有 P0 User Story 必须做到“功能 + 测试”同步交付。
### 2.1 覆盖率目标
| 层级 | 最低目标 |
|---|---|
| `core/` 基础模块 | ≥ 90% |
| `apps/*/services/` 业务逻辑层 | ≥ 80% |
| `apps/*/views*` 接口与视图层 | ≥ 70% |
| `apps/*/tasks.py` 异步任务 | ≥ 70% |
| E2E 核心旅程 | 5 条全部通过 |
### 2.2 质量门禁
- 每个 P0 US 对应至少一个集成测试场景集。
- PR 合并前:单元 + 集成必须全绿。
- `main/develop`:每日自动跑全量(含 E2E 核心旅程)。
---
## 三、测试分层架构
```
┌─────────────────────────────────────────┐
│ E2E 测试(用户旅程) │ ← Playwright
├─────────────────────────────────────────┤
│ 集成测试HTTP / View / Service / DB │ ← pytest-django + TenantClient
├─────────────────────────────────────────┤
│ 单元测试(纯逻辑) │ ← pytest + factory_boy + mock
└─────────────────────────────────────────┘
```
### 3.1 单元测试
- 目标:服务层、工具层、任务函数的逻辑正确性。
- 约束:不启动真实 HTTP不依赖外部网络。
### 3.2 集成测试
- 目标验证完整请求链路View → Service → DB
- 约束:必须使用 `TenantClient`,禁止 Django 原生 `Client()`
### 3.3 E2E 测试
- 目标:验证真实用户关键路径。
- 约束:只覆盖核心旅程,避免把所有细节都堆到 E2E。
---
## 四、工具选型与依赖
| 类型 | 工具 | 版本建议 | 用途 |
|---|---|---|---|
| 测试框架 | `pytest` | ≥ 8.x | 统一运行器 |
| Django 集成 | `pytest-django` | ≥ 4.x | DB/Client/Settings |
| 数据工厂 | `factory_boy` | ≥ 3.x | 生成测试数据 |
| 假数据 | `Faker` | ≥ 25.x | 中文业务数据 |
| Mock | `pytest-mock` | ≥ 3.x | 外部依赖打桩 |
| HTTP Mock | `responses` | ≥ 0.25.x | 三方 HTTP 隔离 |
| 覆盖率 | `pytest-cov` | ≥ 5.x | coverage 报告 |
| 并行 | `pytest-xdist` | ≥ 3.x | 加速单测/集成 |
| E2E | `playwright` + `pytest-playwright` | ≥ 1.44 / ≥ 0.5 | 浏览器自动化 |
安装基线:
```bash
pip install -r requirements/test.txt
playwright install chromium
```
---
## 五、目录结构约定
```text
tests/
├── conftest.py
├── settings_test.py
├── factories/
│ ├── tenant_factory.py
│ ├── account_factory.py
│ ├── permission_factory.py
│ ├── complex_factory.py
│ ├── property_factory.py
│ ├── client_factory.py
│ └── org_factory.py
├── unit/
│ ├── test_encryption.py
│ ├── test_soft_delete.py
│ ├── test_*_service.py
│ └── test_celery_tasks.py
├── integration/
│ ├── account/test_us_account.py
│ ├── permission/test_us_permission.py
│ ├── complex/test_us_complex.py
│ ├── property/test_us_property.py
│ ├── client/test_us_client.py
│ ├── org/test_us_org.py
│ └── setting/test_us_setting.py
└── e2e/
├── conftest.py
├── test_journey_login.py
├── test_journey_property.py
├── test_journey_client.py
├── test_journey_permission.py
└── test_journey_onboarding.py
```
---
## 六、多租户测试约定(强制)
### 6.1 核心原则
1. 所有 DB 测试在租户 schema 上下文执行。
2. 业务数据禁止直接在 `public` schema 断言。
3. 事务隔离默认开启,测试间不得共享可变状态。
4. 测试请求必须经 `TenantClient` 发出。
### 6.2 标准 fixture最小集合
- `tenant`
- `tenant_client`
- `admin_user`
- `staff_user`
- `authenticated_client`
### 6.3 禁止事项
- 禁止手工 `SET search_path`
- 禁止跨租户数据断言
- 禁止在集成测试用 Django 原生 `Client()`
---
## 七、单元测试规范
### 7.1 覆盖范围
| 代码范围 | 示例文件 |
|---|---|
| `core/encryption.py` | `tests/unit/test_encryption.py` |
| `core/models/base.py` | `tests/unit/test_soft_delete.py` |
| `apps/*/services/` | `tests/unit/test_*_service.py` |
| `apps/*/tasks.py` | `tests/unit/test_celery_tasks.py` |
### 7.2 Celery 测试模式
`tests/settings_test.py` 必须启用:
```python
CELERY_TASK_ALWAYS_EAGER = True
CELERY_TASK_EAGER_PROPAGATES = True
```
并统一使用:
```python
result = some_task.apply(args=[...])
```
### 7.3 PII 相关必测点
- 密文不等于明文
- 同明文重复加密产生不同密文(随机 nonce
- 解密结果与原文一致
- 哈希索引稳定(同明文同 hash
---
## 八、集成测试规范
### 8.1 请求模式
| 类型 | Header | 预期 |
|---|---|---|
| 普通页面请求 | 无 | 完整 HTML |
| HTMX 局刷请求 | `HTTP_HX_REQUEST=true` | HTML 片段 |
### 8.2 权限覆盖最小集
每个受保护接口必须覆盖:
1. 有权限:`200`
2. 无权限:`403`
3. 未登录:`302`
### 8.3 User Story 映射基线
| US 范围 | 测试文件 |
|---|---|
| US-ACCOUNT-001~003 | `tests/integration/account/test_us_account.py` |
| US-PERMISSION-001~005 | `tests/integration/permission/test_us_permission.py` |
| US-COMPLEX-001~003 | `tests/integration/complex/test_us_complex.py` |
| US-PROPERTY-001~008 | `tests/integration/property/test_us_property.py` |
| US-CLIENT-001~017 | `tests/integration/client/test_us_client.py` |
| US-ORG-001~003 | `tests/integration/org/test_us_org.py` |
| US-SETTING-001 | `tests/integration/setting/test_us_setting.py` |
### 8.4 外部依赖 Mock 规范
- R2mock `boto3.client`
- Redisfakeredis / locmem cache
- 邮件locmem backend
- 第三方 HTTP`responses` 全量拦截
---
## 九、E2E 测试规范
### 9.1 核心旅程(必须)
| 编号 | 旅程 | 对应模块 |
|---|---|---|
| J-01 | 登录 → 进入首页 | 登录 |
| J-02 | 录入房源 → 上传图片 → 查看列表 | 房源 |
| J-03 | 录入客源 → 添加跟进 | 客源 |
| J-04 | 无权限访问受限页面 | 权限 |
| J-05 | 创建员工 → 分配角色 → 新员工登录 | 组织人事 + 权限 |
### 9.2 Playwright 约束
- 默认 Chromium
- CI 使用 headless
- 禁止 `wait_for_timeout()` 固定等待
- 优先语义等待:`wait_for_url` / `expect(locator)` / `networkidle`
### 9.3 HTMX 页面注意事项
HTMX 更新后 URL 可不变,断言前必须等待请求完成:
```python
page.click('button:has-text("筛选")')
page.wait_for_load_state('networkidle')
```
---
## 十、测试配置基线
### 10.1 `pytest.ini`
```ini
[pytest]
DJANGO_SETTINGS_MODULE = tests.settings_test
python_files = test_*.py
addopts = --tb=short --strict-markers -q
markers =
unit
integration
e2e
slow
```
### 10.2 `tests/settings_test.py` 关键项
- Celery eager 模式开启
- Cache 使用测试后端locmem/fakeredis
- 邮件使用 locmem backend
- 媒体文件使用临时目录
- `DEBUG=False`(贴近生产)
---
## 十一、CI 自动化运行
### 11.1 触发策略
- 每日定时全量测试
- `main/develop` 每次 push 触发
### 11.2 流水线拆分
1. `unit-and-integration`
2. `e2e`(依赖前者成功后执行)
### 11.3 最低产物
- 覆盖率报告(终端 + 平台上传)
- E2E 失败截图 artifact
---
## 十二、AI 协作测试要求
每个 User Story 实现后,必须同时补齐:
- Factory如缺失
- Service 单元测试(正常 + 至少2个边界
- View/API 集成测试(覆盖全部 AC
- 权限三态与 HTMX/普通请求双形态
修复顺序:
1. 先修功能代码
2. 仅当测试确实错误才改测试
3. 本地复跑通过后再提交
---
## 十三、禁止项Do NOT
- 禁止 Django 原生 `Client()` 进行租户集成测试
- 禁止固定等待(`sleep` / `wait_for_timeout`
- 禁止真实调用外部服务
- 禁止测试之间共享可变数据
- 禁止无权限/未登录场景缺失
- 禁止空测试占位后不补全
---
## 十四、文档同步规则
- 新增/调整 User Story同步 `PRD/TASK.md` 与集成测试映射
- 模块 API 变更:同步对应模块技术方案
- 测试目录变更:同步本文件目录结构与 CI 脚本
- 新增测试基建fixture/工具):同步 `AGENTS.md` 与本文件