Covers routing, failover, the circuit breaker, structured-output retries, the cache-prefix validator, cost computation including cached-token pricing, the daily budget breaker, the quota protocol, the task state machine and log redaction. HTTP is mocked -- no unit test spends money. The integration test runs the real slice against PostgreSQL and Redis with a faked provider.
49 lines
2.2 KiB
Markdown
Executable File
49 lines
2.2 KiB
Markdown
Executable File
# `tests/`
|
||
|
||
| 目录 | 内容 | 依赖 |
|
||
| --- | --- | --- |
|
||
| `unit/` | 领域逻辑、LLM 网关、脱敏、错误码 | 无。不许连库、不许发网络请求 |
|
||
| `integration/` | 带 PostgreSQL / Redis 的链路 | `make up`,或 testcontainers |
|
||
| `golden/` | 黄金集回归(检索 / 规则 / 报告) | 尚未建立,见下 |
|
||
|
||
```bash
|
||
make test-unit # 默认只跑 unit(integration 自动跳过)
|
||
MEIDA_RUN_INTEGRATION=1 uv run pytest -m integration
|
||
```
|
||
|
||
## 覆盖率门槛
|
||
|
||
`pytest` 对 `packages/llm` 与 `packages/domain` 统计覆盖率,低于阈值即失败。
|
||
这两个包是 mypy strict 的范围,也是业务正确性的核心,其他层靠集成测试覆盖。
|
||
|
||
## 绝对不要做的事
|
||
|
||
- **不要在单测里调用真实的 DeepSeek**。`scripts/smoke.sh` 是唯一会真的花钱的
|
||
入口。单测用 `httpx.MockTransport` 或 `tests/unit/test_gateway.py` 里的
|
||
`FakeProvider`。
|
||
- 不要 `time.sleep()`。熔断器、预算闸门都支持注入时钟。
|
||
- 不要断言日志文本。断言行为。
|
||
|
||
## 黄金集(还没建,但这是最重要的一道防线)
|
||
|
||
架构 §16.2:
|
||
|
||
> AI 改代码时最容易破坏的是那些「没有断言保护的隐性行为」。检索链路和规则引擎
|
||
> 必须有一套固定输入 → 期望输出的样本集。
|
||
|
||
M2 落地知识库时必须同步建立(FR-KB-11,≥ 100 条用例):
|
||
检索 Top-5 命中率 ≥ 80%、硬过滤零漏、规则命中正确性、报告结构完整性、
|
||
**硬性禁忌违反数 = 0**。指标退化即阻断合并。
|
||
|
||
## 已覆盖的关键不变量
|
||
|
||
| 测试 | 保护的是什么 |
|
||
| --- | --- |
|
||
| `test_prompt_cache_prefix.py` | 固定前缀不含易变 token,否则输入成本翻数倍 |
|
||
| `test_daily_budget.py` | 日成本超限时**拒绝**非关键调用,不是只告警 |
|
||
| `test_gateway.py` | 路由、故障转移、熔断、结构化重试、每次调用都记成本 |
|
||
| `test_quota_domain.py` | 预扣三段式;退还幂等;服务端硬校验 |
|
||
| `test_task_state.py` | 任务状态机没有非法跃迁 |
|
||
| `test_log_redaction.py` | 手机号 / 令牌 / 密钥 / 诊断结论不进日志 |
|
||
| `test_response_envelope.py` | 每个错误码都有文案;配额文案不含价格字样 |
|