Files
ocean/backend/tests/README.md
T

45 lines
2.5 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.
# 后端 API 测试(TDD
依据《产品文档》与《API 文档》,用 Python + pytest 编写。**先写失败用例(RED),再实现路由(GREEN)。**
## 测试与开发环境严格隔离
- **不加载应用代码、不 mock 认证**:测试通过 HTTP 请求**已启动的后端服务**,与开发环境完全隔离。
- **运行方式**:先启动后端服务(如 `uvicorn` 监听 `http://0.0.0.0:8000`),再在另一终端执行 `pytest tests/ -v`
- **服务地址**:默认 `http://127.0.0.1:8000`,可通过环境变量 `TEST_BASE_URL` 覆盖。
## 登录与带 Token 调用
- **登录**`POST /api/auth/login`,请求体 `{"username": "admin", "password": "123456"}`(或 `market` / `engineer` / `tech` / `finance` / `material`,密码均为 `123456`)。
- **带 Token 调接口**:在请求头中加 `Authorization: Bearer <登录返回的 token>`,再调用项目列表、详情、新建、更新、操作日志等接口。
- **Fixture**`conftest.py` 提供 `auth_token`admin)、`market_token`(市场部)、`engineer_token`(工程部),用例中直接注入使用。
## 运行测试
```bash
# 1. 先启动后端(在 backend 目录或项目根目录)
uvicorn src.app:app --host 0.0.0.0 --port 8000
# 2. 在另一终端运行测试
cd backend
source .venv/bin/activate # 或 pip install -r requirements.txt
pytest tests/ -v
```
如需指定服务地址:
```bash
TEST_BASE_URL=http://localhost:8000 pytest tests/ -v
```
## 用例覆盖
| 接口 | 用例 |
|------|------|
| POST /api/auth/login | 成功返回 token/user、错误凭证 401、缺 username/password 返回 400 |
| POST /api/projects/list | 无 token 401;有 token 返回 list/total/page/pageSize;无数据 list 空且 total=0;支持 searchType+keyword(name/code)、progress、cost、dateFilterType+dateFrom/dateTo、dateAbnormal;列表项含 id/projectName/contractCode/progress/cost/updatedAtpage/pageSize 回显 |
| POST /api/projects/detail | 无 token 401、缺 id 400/422、存在项目返回完整五类字段、不存在 404 |
| POST /api/projects/create | 无 token 401、非市场部 403、市场部且必填齐全 201、缺合同编号/项目名称 400、校验失败可含 errors 数组 |
| POST /api/projects/update | 无 token 401、缺 id 400/422、存在项目 200 保存成功、不存在 404 |
| POST /api/projects/logs | 无 token 401、缺 id 400/422、有 token 返回 list/total/page/pageSize、不存在项目 404、更新后有一条含 summary 的日志、列表项含 id/operatorId/operatorName/operatedAt/summary |