chore(pbl_evidence): 收口 README.md 遗留未提交变更(DISC.2 测试环境章节,非本任务改动)

本任务(api.py 主键落地)范围边界=仅 api.py。README.md 的 86 行新增是上一子任务
(DISC.2 测试前置依赖说明)留在工作区未被收口的内容,本次**未修改其一个字**,
仅单独 commit 收口,以免与 378c024 的 api.py 改动混在同一提交里造成范围误判。
This commit is contained in:
agent.develop 2026-09-22 22:07:12 +08:00 committed by agent.develop
parent 57f651fd79
commit 4522a1a6dd

View File

@ -213,6 +213,92 @@ python3 scripts/selfcheck_m5a.py
> `SDLC_WS_ROOT`(配合可选 `SDLC_PROJECT` 覆盖项目名,默认 `pbls`)时生效;定位不到工作空间
> 根时这三项返回 `SKIPPED`(不计 FAIL),避免别的宿主挂载本模块时把「路径不存在」误判成质量回归。
## Running tests(测试前置依赖与执行方式,发现项 DISC.2)
> 本节是 `scripts/setup_test_env.sh` 报错文案所指向的排障入口,**必须存在**(QC #12)。
> 同时回答两个问题:① pytest 依赖声明在哪里;② 不手工注入 `PYTHONPATH` 怎么把测试跑绿。
### 为什么需要这一节(DISC.2 根因)
测试机宿主 `python3` **没有** pytest,`python3 -m pytest` 直接 `No module named pytest`;
而宿主 user site(`/d/pipeline/.local/lib/python3.10/site-packages`)在本机是**只读文件系统**,
`pip install --user pytest` 会以 `[Errno 30] Read-only file system` 失败。此前靠临时注入
`PYTHONPATH=<workspace>/.pylibs`(pytest 9.1.1)跑通,属一次性手段——换机器/换角色即失效,
test 角色据此会误判「用例失败/环境不可用」。**正确落点是显式声明 + 一条命令引导到 venv。**
### 依赖声明在哪(两份,版本区间同源 `>=7.0,<10`)
| 文件 | 作用域 | 谁装它 |
|---|---|---|
| `requirements-dev.txt`(本模块) | 模块级:不安装本包也能跑离线单测的最短路径(CI / 测试机宿主) | `scripts/setup_test_env.sh` |
| `pyproject.toml` → `[project.optional-dependencies].test` | 包级:`pip install -e .[test]` | 已装本包的场景 |
| `apps/pbls/requirements-test.txt` | 应用级:随 `build.sh` 第 7b 步进 venv | `apps/pbls/build.sh` |
三者版本区间一致(下限 7.0 要 `pytest.mark.skipif` 与 `monkeypatch(raising=)` 稳定语义;
上限 <10 不自动跟随主版本跳变)。pytest 属**测试**依赖,绝不写进 `[project].dependencies`。
### 三条真实可执行路径
```bash
# A) 一条命令引导 + 跑(推荐,无 pytest 时自动建 .venv-test 并装 requirements-dev.txt)
cd modules/pbl_evidence && bash scripts/run_tests.sh
# 等价显式写法:bash scripts/run_tests.sh tests/test_m5a_idempotency.py -v
# 同时落盘日志:bash scripts/run_tests.sh --log ../../projects/pbls/docs/02-develop/m5a-disc2-pytest-run.log
# B) 只引导环境,之后自己用 venv 解释器
bash scripts/setup_test_env.sh
bash scripts/activate_test_env.sh # 打印 source 命令;或直接:
.venv-test/bin/python -m pytest tests/test_m5a_idempotency.py -v
# C) 走应用构建链(venv 内即有 pytest,由 build.sh 第 7b 步安装)
bash apps/pbls/build.sh
source apps/pbls/venv/bin/activate && python3 -m pytest modules/pbl_evidence/tests/test_m5a_idempotency.py -v
```
`run_tests.sh` 的解释器解析顺序:`PBL_EVIDENCE_TEST_PYTHON` → 宿主 `python3`(能 import pytest 才用)
→ `${PBL_EVIDENCE_TEST_VENV}/bin/python`(默认 `.venv-test`);三者都没有 pytest 时自动调用
`setup_test_env.sh` 引导,引导失败 exit 3(不会伪装成测试失败)。
### 环境变量
| 变量 | 含义 | 缺省 |
|---|---|---|
| `PBL_EVIDENCE_TEST_VENV` | 测试 venv 落点 | `<module>/.venv-test`(已在 `.gitignore`) |
| `PBL_EVIDENCE_TEST_PYTHON` | 强制指定解释器 | 空(按上面顺序解析) |
| `PBL_EVIDENCE_INSTALL_PKG` | 置 `1` 时额外 `pip install -e .` | `0` |
| `PBL_EVIDENCE_TEST_DB` | 真实库开关,见下节 | 空(DB 用例 SKIPPED) |
| `PBL_EVIDENCE_TEST_TENANT` | DB 用例使用的租户 | `m5a-idem-test` |
| `PIP_INDEX_URL` | 内网 PyPI 源 | 空(用 pip 自身配置) |
### `test_double_collect_is_idempotent_with_db` 的开关用法
该用例需要**真实 MariaDB**(双次采集 → 断言第二次不产生新行),未设开关时按设计
`SKIPPED`——这是预期结果,不是失败,也不是环境不可用。可执行路径:
```bash
# 1) 库与表就位(pbl_artifact / pbl_evidence 由 apps/pbls/build.sh 第 10 步建表)
# 2) 带开关运行:DSN 形如 mysql://user:pwd@host:3306/pbls
PBL_EVIDENCE_TEST_DB='mysql://<user>:<pwd>@<host>:3306/<dbname>' \
PBL_EVIDENCE_TEST_TENANT=m5a-idem-test \
bash scripts/run_tests.sh tests/test_m5a_idempotency.py -v
# 期望:9 passed, 0 skipped
```
不带开关时的期望结果(本机实测,日志见
`projects/pbls/docs/02-develop/m5a-disc2-pytest-run.log`):`8 passed, 1 skipped`,RC=0。
### 排障
| 现象 | 原因 | 处理 |
|---|---|---|
| `安装 pytest 失败:检查内网 PyPI 源可达性` | 内网源不可达 / 无代理 | 先 `curl -I ${PIP_INDEX_URL:-https://pypi.tuna.tsinghua.edu.cn/simple}`;离线环境用 `PIP_NO_INDEX=1 PIP_FIND_LINKS=/path/to/wheels bash scripts/setup_test_env.sh`(需预置 pytest+pluggy+iniconfig+packaging+tomli+exceptiongroup+pygments 的 wheel) |
| `pip install --user` 报 `Read-only file system` | 宿主 user site 只读(本机即如此) | **不要**再试 `--user`,走 venv(路径 A/B) |
| 报 venv 落点未被 `.gitignore` 忽略 | 仓库卫生门禁(QC #1 曾误入库 1171 个文件) | 在 `.gitignore` 补 `.venv-test/` 并 `git rm -r --cached .venv-test`,再重跑 |
| `No module named pytest` 但已跑过 build.sh | 构建时设了 `PBL_SKIP_TEST_DEPS=1` | 去掉该开关重跑 `build.sh`,或走路径 A |
| 用例里 DB 相关断言被跳过 | 未设 `PBL_EVIDENCE_TEST_DB` | 见上节开关用法 |
**禁止**为凑通过修改测试断言逻辑(DISC.2 的验收前提)。
## Integration(宿主挂载方式)
模块只依赖:基础包(sqlor、ahserver ServerEnv、appPublic 工具)、`pbl_common`(租户上下文/