- git rm scripts/patch_build_7b.py(一次性构建期补丁脚本,移出应用仓;证据附件保留在 projects/pbls/docs/02-develop/patches/m5a-disc2-patch_build_7b.py) - README §期望结果:场景 1 / 场景 2 分别对应各自实测日志,不再以场景 2 日志代证场景 1, 并如实记录场景 1 的受控截取执行方式与两处既有问题(内网源不可达、DDL 方言门禁命中注释)
98 lines
6.4 KiB
Markdown
98 lines
6.4 KiB
Markdown
# pbls
|
||
|
||
PBL Agent OS 验证原型应用(唯一入口 `app/pbls.py`,端口以
|
||
`projects/pbls/env/test.json` 为唯一事实源)。业务模块见机构 `modules/pbl_*`。
|
||
|
||
## 测试依赖(DISC.2)
|
||
|
||
**结论:pytest 已显式声明,不再依赖临时注入 `PYTHONPATH`。** 宿主 `python3` 上没有 pytest
|
||
(`python3 -m pytest` → `No module named pytest`),且本机宿主 user site 是只读文件系统
|
||
(`pip install --user` 报 `[Errno 30] Read-only file system`),所以测试依赖的落点是 **venv**。
|
||
|
||
### 新增/相关文件清单
|
||
|
||
| 路径 | 层级 | 职责 |
|
||
|---|---|---|
|
||
| `apps/pbls/requirements-test.txt` | 应用级 | 测试前置依赖清单(`pytest>=7.0,<10`),由 `build.sh` **第 7b 步**装进应用 venv |
|
||
| `apps/pbls/build.sh` 第 7b 步 | 应用级 | `pip install -r requirements-test.txt` + `import pytest` 自证;`PBL_SKIP_TEST_DEPS=1` 可跳过 |
|
||
| `modules/pbl_evidence/requirements-dev.txt` | 模块级 | 同一版本区间的模块侧清单(不装本包也能跑离线单测的最短路径) |
|
||
| `modules/pbl_evidence/scripts/setup_test_env.sh` | 模块级 | 建 `.venv-test` 并安装 `requirements-dev.txt`(含仓库卫生门禁) |
|
||
| `modules/pbl_evidence/scripts/activate_test_env.sh` | 模块级 | 打印激活/直接调用测试 venv 解释器的方式 |
|
||
| `modules/pbl_evidence/scripts/run_tests.sh` | 模块级 | 一条命令跑测试:无 pytest 时自动引导,再执行 pytest |
|
||
| `modules/pbl_evidence/README.md` §Running tests | 文档 | 排障入口 + `PBL_EVIDENCE_TEST_DB` 开关用法 |
|
||
|
||
### 为什么是两份清单(应用级 vs 模块级)
|
||
|
||
- `requirements-test.txt`(应用级)服务**整应用**的测试环境:跑 `build.sh` 后 venv 内即有 pytest,
|
||
任何 `modules/pbl_*/tests/` 都能用同一个解释器执行。
|
||
- `requirements-dev.txt`(模块级)服务**只测本模块**的 CI/离线场景:不安装 pbls 应用、不装本包
|
||
(`pip install -e .`)也能一条命令装好依赖。
|
||
- 两份**版本区间同源**(`>=7.0,<10`),避免"应用装了 9.x、模块 CI 装了 7.x"导致用例语义漂移。
|
||
- 两者都刻意与运行时清单 `requirements.txt` 分离:pytest 不进生产镜像,也不进
|
||
`build.sh` 第 5 步的运行时依赖核验(该步只核验 ahserver/sqlor/apppublic/appbase/rbac/PyMySQL)。
|
||
|
||
### 推荐调用顺序
|
||
|
||
```bash
|
||
# 场景 1:完整应用环境(部署/联调机)
|
||
bash apps/pbls/build.sh # 第 7 步 venv → 7b 测试依赖 → 8 装模块
|
||
source apps/pbls/venv/bin/activate
|
||
python3 -m pytest modules/pbl_evidence/tests/test_m5a_idempotency.py -v
|
||
|
||
# 场景 2:只跑 pbl_evidence 单测(测试机/CI,最短路径)
|
||
bash modules/pbl_evidence/scripts/run_tests.sh # 无 pytest 时自动引导 .venv-test
|
||
|
||
# 场景 3:只要环境不要跑(手工用 venv 解释器)
|
||
bash modules/pbl_evidence/scripts/setup_test_env.sh
|
||
bash modules/pbl_evidence/scripts/activate_test_env.sh
|
||
```
|
||
|
||
### 期望结果与实测证据(两个场景各对应一份日志,不互相代证)
|
||
|
||
期望输出(两场景相同):
|
||
|
||
- 不带 `PBL_EVIDENCE_TEST_DB`:`8 passed, 1 skipped`,RC=0
|
||
(`test_double_collect_is_idempotent_with_db` 需真实 MariaDB,未设开关时按设计 SKIPPED,属预期)。
|
||
- 带 `PBL_EVIDENCE_TEST_DB`(用法见 `modules/pbl_evidence/README.md` §Running tests):`9 passed`。
|
||
- 禁止为凑通过修改测试断言逻辑。
|
||
|
||
| 场景 | 解释器 | 实测日志 | 状态 |
|
||
|---|---|---|---|
|
||
| **场景 1**(`build.sh` 第 7b 步 → 应用 venv 内 pytest 可用) | `apps/pbls/venv/bin/python` | `projects/pbls/docs/02-develop/m5a-disc2-build7b-run.log` | **已实测** |
|
||
| **场景 2**(模块级引导 `run_tests.sh` / `.venv-test`) | `modules/pbl_evidence/.venv-test/bin/python` | `projects/pbls/docs/02-develop/m5a-disc2-pytest-run.log` | **已实测** |
|
||
|
||
场景 1 日志中的关键真实输出行(由 shell `tee` 捕获,非手写):
|
||
|
||
```
|
||
[build.sh][...] 7b 自证通过: pytest 9.1.1 @ /d/pipeline/workspaces/0/sdlc_general/apps/pbls/venv/bin/python
|
||
[verify] PYTHONPATH = [<unset>]
|
||
========================= 8 passed, 1 skipped in 0.04s =========================
|
||
# pytest RC=0
|
||
```
|
||
|
||
即:7b 段把 pytest 装进应用 venv 后,`source apps/pbls/venv/bin/activate` 且 **PYTHONPATH 未设置**
|
||
的情况下直接跑 pytest 得到 `8 passed, 1 skipped` + RC=0 —— 证明 DISC.2 的原始痛点(靠临时注入
|
||
`PYTHONPATH=<ws>/.pylibs` 才跑得通)已被消除。
|
||
|
||
#### 场景 1 的执行方式(受控截取,未强跑全流程)与已知限制
|
||
|
||
`build.sh` 第 8~14 步需要 MariaDB 建表、种子注入并启动应用,为验证 7b 而强跑全流程会污染测试库,
|
||
因此场景 1 的日志是用 `projects/pbls/docs/02-develop/patches/m5a-disc2-build7b-runner.sh`
|
||
**按标记行从 `build.sh` 原样截取**「头部(`set -euo pipefail` + 变量 + `log()`/`die()`)+ 第 7 步
|
||
venv 创建与 pip 升级 + 完整 7b 段」后 `bash` 执行、`tee` 捕获得到,`build.sh` 本体一个字节未改
|
||
(日志末尾附该文件 md5 以供核对)。日志中同时打印了实际执行的截取脚本(`cat -n`)供逐行复核。
|
||
|
||
两处如实说明(均属本任务范围外的既有问题,已作为发现项上报 PM,未在本任务内改动):
|
||
|
||
1. 截取时**跳过**了第 7 步的 `pip install -r requirements.txt`:该步指向机构内网 PyPI 源
|
||
`http://10.20.30.41:8081`,本工作空间不可达(`curl` rc=124),会先于 7b 失败退出。
|
||
因此场景 1 日志证明的是「7b 段自身可执行并让 pytest 在应用 venv 内可用」,
|
||
**不代表**运行时依赖(ahserver/sqlor/…)在本机已装齐,也不代表 `build.sh` 全流程在本机跑通。
|
||
2. 首轮曾按「截取第 1 行起的全部前缀」执行,`build.sh` 第 4 步 DDL 方言门禁 die:
|
||
`grep -Eiq '...|REFERENCES|ENUM\(|TIMESTAMP'` 命中了 `scripts/ddl/pbls_tables.sql` 里的
|
||
**说明性注释文字**(第 6 行「禁止 FOREIGN KEY / 禁止 ENUM / 禁止原生 TIMESTAMP(用 DATETIME)」、
|
||
第 891 行同类声明),而非真实建表语句。该门禁与 DDL 注释的冲突是既有问题(与 DISC.2 无关),
|
||
修它需要改第 4 步 grep 或改 DDL 注释,超出本任务范围,故本次截取范围从第 7 步起。
|
||
结论:`build.sh` 第 0~6 步门禁本次**未实测**(静态核验 + 首轮部分实跑:第 0~3 步与 6.1/6.2
|
||
真实通过,第 4 步因上述注释冲突 die),第 7b 步**已实测**。
|