fix(tests): Resolve pytest session binding issues and update test cases
- Updated test files to import `AgentSessionLocal` from `advisor_db` instead of directly, preventing session binding to the real database during tests. - Fixed 6 test cases to use the new login token utility, ensuring consistency across authentication methods. - Adjusted customer risk codes in `test_convert_confirm.py` to reflect changes in customer classification (C3 to C4). - Verified that changes resulted in zero database pollution during test runs, maintaining integrity of the testing environment. - Documented findings and updates in the relevant test logs and memory files, ensuring clarity on the current state of tests and defects.
This commit is contained in:
@@ -152,6 +152,7 @@
|
||||
|
||||
**本轮复跑实测 49 passed / 28 failed,与 Phase 0 完全一致** ⇒ **证明是既有问题,不是本轮引入**。这正好实证了上一轮 `MEMORY.md` 里「⚠️ 复跑新发现(需拍板)」的第 ② 条:**「P1 修复可能收窄了业务能力」**。
|
||||
→ **只报告不修**。**更新 2026-09-13:此项已查清** —— 业务上 R4 的"需揭示 → 自助端阻断"**方向正确**(L0 矩阵刻意设三态 + 答辩稿「C3×R4 揭示 block」+ 前端 `canSelfServe:false`),**28 条失败是测试前提过期而非接口缺陷**。完整依据、建议与反向禁忌见 **§8.2**。
|
||||
→ **✅ 已修(2026-09-13 修复轮 · 选 A)**:`test_convert_confirm.py` 客户档位 C3→C4(`C4×R4=allowed`),四文件 **77 passed / 0 failed**;**零业务代码改动**,未补 `forced_full_transfer`(遵守反向禁忌)。
|
||||
|
||||
#### **F-γ —— `core_share_lot` 的基线读数与快照不符(**本轮更正口径**)
|
||||
|
||||
@@ -185,6 +186,8 @@
|
||||
|
||||
> **纪律说明:** 探针写进**真库**而非 sqlite 假库,是本项目"19 个 `test_sprint*.py` 伪造全部 Core 数据源"的**反面同源问题** —— 有的是"假数据源导致测不出接缝",有的是"真数据源被测试写坏"。两者都值得在修复轮立项。
|
||||
|
||||
> **✅ 已修(2026-09-13 修复轮)**:根因实为测试文件**模块级** `from app.advisor_db import AgentSessionLocal` 在收集期绑定真库 sessionmaker、绕过 fixture 的 `monkeypatch`(不单是 `import_script_templates.py:14`)。修法:① 10 个 `test_sprint*.py` 改 `from app import advisor_db` + 调用点 `advisor_db.AgentSessionLocal`/`advisor_db.agent_engine`;② `import_script_templates.py` 同改;③ 唯一写真库的 subprocess 用例(seed 脚本独立跑)改 `@pytest.mark.skip`(另两处 subprocess `sync_template_vectors --dry-run` / `evaluate_compliance` 经查**只读**)。**验证**:跑后 `script_template` 仍 **65 / seed 20 / `test:*` 36**,零污染。**同轮另修**:6 个 `test_sprint2_*.py` 的陈旧登录契约(`/api/v1/auth/login` + `{username,password}` → `tests/advisor_test_utils.login_token`)。**副作用(如实)**:转 sqlite 后暴露 **F-α 假 DDL 缺列**(`agent_session` 无 `metadata` 等),sprint 组 45 条失败为陈旧 DDL/期望,非本轮引入。
|
||||
|
||||
#### **F-ζ —— `--ignore-glob=test_sprint*.py` 是**空操作**(本轮新发现)**
|
||||
|
||||
`docs/答辩/DEMO-功能测试流程.md` A3 的门槛命令写着 `pytest -q --ignore-glob=test_sprint*.py`。**实测该 flag 一个文件都没过滤掉:**
|
||||
@@ -286,6 +289,7 @@
|
||||
> **拍板结论:维持现状语义不动,下一轮只改测试(客户档位 C3→C4 或产品 R4→R3),零业务代码改动。**
|
||||
> **规则固化(答辩口径同此)**:`C3×R4` / `C4×R5` = **匹配但需揭示** ⇒ **自助渠道阻断并引导线下**,这是**设计意图,不是缺陷**。
|
||||
> **禁止项**:不得给阻断响应体补 `forced_full_transfer` 让测试变绿(=让"阻断"伪装成"受理成功")。选项 B(做揭示书 Modal)**已否决**,若日后要做属独立需求轮。
|
||||
> **✅ 已执行(2026-09-13 修复轮)**:`test_convert_confirm.py` 客户档位 **C3→C4**(`C4×R4=allowed`),四文件 **77 passed / 0 failed**;`CUST_LOW`(C1) 阻断用例保留作 T+1 复核对照;阻断响应体仍**不含** `forced_full_transfer`。
|
||||
|
||||
以下为支撑该结论的原始取证(存档备答辩追问):
|
||||
|
||||
@@ -352,6 +356,7 @@ python -m pytest -q --ignore-glob='*/test_sprint*.py'
|
||||
| 2 | **`/app/home` 与 `/app` 两个路由未访问** | 同上,XC2 未执行。`08-edge` 只验了"未知路由重定向到角色首页",**不等于**访问过 `/app/home` 本身 |
|
||||
| 3 | **XC3 的面包屑 / 登出 / 会话侧栏切换未做浏览器验证** | GX4 只从 **HTTP 侧**验了 `close-all`/`sessions`/`{id}/close`;**前端按钮点击路径未验** |
|
||||
| 4 | **测试套件不可复现(F-η)** | 单次 `pytest` 结果随库状态漂移。**引用其数字必须附跑批序号与库状态** |
|
||||
| 5 | **F-ε 的根因仍在** | 本轮只**还原**,未修 `import_script_templates.py` 的**模块级 session 绑定**。**再跑一次 pytest 污染即复现** |
|
||||
| 6 | **28 条交易单测失败未消解** | 根因已查清=**测试前提过期**(非接口缺陷);修法已给(改测试客户档位 C3→C4 / 产品 R4→R3),**待点头后下一轮执行,不在本轮范围**。见 §8.2 |
|
||||
| 5 | ~~F-ε 根因仍在~~ **已修(2026-09-13 修复轮)** | 10 个 `test_sprint*.py` 改模块属性访问 + skip 写真库 subprocess 用例;验证零污染(`script_template` 65/20/36 前后一致)。**副作用**:转 sqlite 后暴露 F-α 假 DDL 缺列(见 §6.2) |
|
||||
| 6 | ~~28 条交易单测失败未消解~~ **已修** | 选 A 已执行(客户档位 C3→C4),四文件 **77/0**。见 §8.2 |
|
||||
| 7 | **P0 mock 登录无 `app_env` 门禁** | 已拍板「本轮不动,只记录」(2026-09-13)。`/api/auth/login`(`app/api/auth.py:16`)无条件挂载 ⇒ 生产也能签白名单角色 token。**留待部署前修**:`login()` 内 `app_env != "development"` 即 403/404,或仅 development 条件挂载 router。当前 `APP_ENV=development`,加门禁不影响 demo |
|
||||
| 7 | `GX4-07`/`GX4-08` 两条状态机/越权路径未覆盖 | 见 §三 SKIP 说明 |
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
| 文档版本 | v1.0 |
|
||||
| 创建日期 | 2026-09-13 |
|
||||
| 关联分支 | `merger` |
|
||||
| 关联拍板/TODO | **已收敛(2026-09-13 用户拍板)**:**F-14 维持现状** · **RK 发现-1 关闭** · **F-β 已查清待点头**(结论:现状"阻断"方向正确,缺陷在测试侧;见 README §8.2) |
|
||||
| 风险等级 | **MEDIUM**(F-β 的 28 条单测失败**未消解**;F-ε 根因仍在;套件非幂等) |
|
||||
| 关联拍板/TODO | **已收敛 + 修复轮落地(2026-09-13)**:**F-14 维持现状** · **RK 发现-1 关闭** · **F-β 选 A 并已执行**(测试档位 C3→C4,77/0)· **F-ε 已修**(零污染验证)· **P0 mock 登录门禁「本轮不动,只记录」** |
|
||||
| 风险等级 | **MEDIUM**(F-β / F-ε 已修;仍开放:F-α 假 DDL 缺列 · F-η 套件非幂等 · P0 mock 登录无门禁[defer] · 「网点办理」无通路) |
|
||||
| 缺陷类型 | 测试基建(腐化/污染/非幂等)· 文档门槛陈旧 · 编号歧义 · 数据还原 |
|
||||
| 发现阶段 | 端到端覆盖缺口补测轮 · Part A/B/C + Phase 6 |
|
||||
|
||||
@@ -74,8 +74,8 @@
|
||||
| 复现步骤 | 见 §5 执行记录第 4~6 条与 §6 数据准备 |
|
||||
| 期望 | 测试隔离,不写真实业务库;同一条命令连跑结果一致 |
|
||||
| 实际 | ① `pytest` 后 `script_template` **47 → 65 行**,20 条演示模板被翻成 `is_approved=0`,**页面可见 20 → 6**;② `jinrong_core` 5 表亦被写入(`102/62/81/23/0` → `103/62/86/26/0`);③ **连跑两次的 FAIL/ERROR 集合不同**(129 行 vs 127 行) |
|
||||
| 根因 | `scripts/seed/import_script_templates.py:14` 在**模块级**绑定 `AgentSessionLocal`,而 `tests/test_sprint2_template_import.py` 的 seed 调用**未请求** `_advisor_agent_sqlite_db` fixture ⇒ 写真库且不回滚 |
|
||||
| 修复方案 | **本轮只还原,不改根因**(属测试基建立项)。**还原已执行且可复现**:见 §6。**⚠️ 再跑一次 pytest 污染即复现** |
|
||||
| 根因 | 测试文件**模块级** `from app.advisor_db import AgentSessionLocal` 在收集期绑定真库 sessionmaker,绕过 fixture 对 `app.advisor_db.AgentSessionLocal` 的 monkeypatch(不单是 `import_script_templates.py:14` 一处);另有 seed 脚本独立 subprocess 写真库 |
|
||||
| 修复方案 | **已修(2026-09-13 修复轮)**:① 10 个 `test_sprint*.py` 改 `from app import advisor_db` + `advisor_db.AgentSessionLocal`/`advisor_db.agent_engine`;② `import_script_templates.py` 同改;③ 唯一写真库的 subprocess 用例(seed 脚本独立跑)改 `@pytest.mark.skip`(另两处 subprocess `sync_template_vectors --dry-run` / `evaluate_compliance` 经查只读)。**验证**:跑后 `script_template` 仍 65/20/36,零污染 |
|
||||
|
||||
## 4. 变更清单
|
||||
|
||||
@@ -99,9 +99,10 @@
|
||||
| **F-05** | `scripts/e2e/09/10/11` harness 指向 | 仓库内外 harness **已分叉**(9301 B vs 6049 B) | 逐支改指向 `scripts/e2e/harness.mjs`,核对原语;**先跑通一支再收下一支**(R8) | ✅ 已修 |
|
||||
| **F-06** | 截图路径 | `_raw/shots/` 固定常量 ⇒ 四包互相顶掉(上轮已丢 v1.0 截图) | **零代码改动**:用 `E2E_SHOT_DIR` env(`harness.mjs:39` 早已支持) | ✅ 已修 |
|
||||
| **F-α** | `docs/答辩/…` A3 门槛 | 称 `896 passed`,实测 1236 | 只报告;以实测为基线 | 📝 记录 |
|
||||
| **F-β** | `tests/test_convert_confirm.py` | 固化旧语义 ⇒ `KeyError: forced_full_transfer`,28 条失败 | **只报告**。**已查清(2026-09-13)**:根因是**测试前提过期**(`forced_full_transfer` 属受理成功路径字段,C3 被阻断后受理未发生),**非接口缺陷**;建议下一轮改测试客户档位 C3→C4 / 产品 R4→R3。**⚠️ 不得给阻断响应体补该键**。见 README §8.2 | 📝 记录 |
|
||||
| **F-β** | `tests/test_convert_confirm.py` | 固化旧语义 ⇒ `KeyError: forced_full_transfer`,28 条失败 | **已修(选 A)**:测试客户档位 C3→C4(`C4×R4=allowed`),四文件 **77 passed / 0 failed**。零业务代码改动,未补 `forced_full_transfer`。见 README §8.2 | ✅ 已修 |
|
||||
| **F-γ** | Phase 0 基线口径 | "74"读数与该次快照(73 行)不自洽 | 还原判据改为**与快照逐表 CHECKSUM 一致** | ✅ 已更正 |
|
||||
| **F-ε** | `scripts/seed/import_script_templates.py:14` | 模块级 session 绑定 ⇒ pytest 写真库 | **本轮只还原**(根因未修) | ⚠️ 已还原 |
|
||||
| **F-ε** | 10 个 `test_sprint*.py` + `import_script_templates.py` | 模块级 `from app.advisor_db import AgentSessionLocal` 收集期绑真库 ⇒ pytest 写真库 | **已修**:改模块属性访问 `advisor_db.AgentSessionLocal` + skip 写真库 subprocess 用例。验证零污染(`script_template` 65/20/36 前后一致) | ✅ 已修 |
|
||||
| **陈旧登录契约** | 6 个 `test_sprint2_*.py` 的 `token_for` | 打 `/api/v1/auth/login` + `{username,password}`,与现行 `POST /api/auth/login`(`actor_id`+`token_type`+`roles`)不符 ⇒ 404/422 | **已修**:迁移到 `tests/advisor_test_utils.login_token`(已有 compat 映射)。6 文件全改,无 `/api/v1` 残留 | ✅ 已修 |
|
||||
| **F-ζ** | 门槛命令 | `--ignore-glob=test_sprint*.py` 为空操作 | 只报告;给出修正写法 | 📝 记录 |
|
||||
| **F-η** | 测试套件 | 非幂等:连跑两次 FAIL 集合不同 | 只报告;引用数字须附跑批序号 | 📝 记录 |
|
||||
|
||||
@@ -155,12 +156,13 @@
|
||||
| 项 | 结论 |
|
||||
| --- | --- |
|
||||
| 需求覆盖 | 横切面:**孤立路由 5 组**(含★零覆盖的 `threshold-check`)· **浏览器跨角色/响应式/对话/边界 4 支** · **测试基建台账 F-α…F-η + F-01…F-06** · **Phase 6 数据还原校验** |
|
||||
| 回归 | ⚠️ **部分退步(但非本轮引入)**:`npm run build` ✅ 退出码 0 · `npm run test` ✅ 27 passed · **四文件交易单测 ❌ 49/28(F-β,与 Phase 0 完全一致)** · `pytest` ❌ 1236/102/9/21(F-α + F-ζ) |
|
||||
| 剩余风险 | ① **F-β 的 28 条单测失败未消解** —— 根因已查清为**测试前提过期**(非接口缺陷),待点头后下一轮改测试(README §8.2);② **F-ε 根因仍在**(再跑 pytest 污染即复现);③ **F-η 套件非幂等** ⇒ 单次 passed 数不可作可靠基线;④ `/register` 等三项前端覆盖**本轮未做**(见 README §十一);⑤ **新增:文案引导的「网点办理/请联系持证投顾」无实现通路**(理财师线零交易 API)—— 见 README §8.3 |
|
||||
| 建议人工再验 | ① `python scripts/dev/gap_routes_e2e_smoke.py` 目视 `threshold-check` 三角色返回;② 打开 `/app/risk/home` 确认 `pending_review=35` 下 KPI 自洽;③ **拍板 F-β / F-14 / RK 发现-1 三项**后再开修复轮 |
|
||||
| 回归 | ✅ **修复轮后(2026-09-13)**:四文件交易单测 **77/0**(F-β 已修)· `test_sprint2_template_import.py` **3/0/1 skip**(F-ε 已修)· `pytest` 非 sprint **1199/45/9/21**(F-α 假 DDL 残留 + F-ζ 修正写法)· `npm run build`/`npm run test` ✅ 未退步 |
|
||||
| 剩余风险 | ① ~~F-β~~ ~~F-ε~~ **已修(修复轮)**;② **F-α 假 DDL 缺列**(`agent_session` 无 `metadata` 等)→ sprint 组 45 条失败为陈旧 DDL/期望,**只记录**;③ **F-η 套件非幂等** ⇒ 单次 passed 数不可作可靠基线;④ `/register` 等三项前端覆盖**未做**(见 README §十一);⑤ **新增:文案「网点办理/请联系持证投顾」无实现通路**(理财师线零交易 API)—— 见 README §8.3;⑥ **P0 mock 登录无 `app_env` 门禁**(已拍板「本轮不动,只记录」,留待部署前修) |
|
||||
| 建议人工再验 | ① `python scripts/dev/gap_routes_e2e_smoke.py` 目视 `threshold-check` 三角色返回;② 打开 `/app/risk/home` 确认 `pending_review=35` 下 KPI 自洽;③ F-β/F-14/RK 发现-1 已拍板并**修复轮已执行**;④ 部署前补 P0 mock 登录门禁 |
|
||||
|
||||
## 8. 签核 / 修订历史
|
||||
|
||||
| 版本 | 日期 | 修订人 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| v1.0 | 2026-09-13 | 本轮补测 | 首次建立:GX1–GX5 + Part B 四支 + Part C 门槛 + 测试基建台账 + Phase 6 还原校验 |
|
||||
| v1.1 | 2026-09-13 | 修复轮 | F-β 选 A 已执行(C3→C4,77/0)· F-ε 已修(模块属性访问 + skip subprocess,零污染)· 6 个 sprint2 陈旧登录契约已迁移 · P0 mock 登录门禁「本轮不动,只记录」 |
|
||||
|
||||
Reference in New Issue
Block a user