deliver: 交付收口(引擎代为提交)
This commit is contained in:
parent
be1c9778c8
commit
e9baafc0d7
@ -204,7 +204,7 @@ python3 scripts/selfcheck_m5a.py
|
||||
> | V2 | `tests/m5a_live_db_harness.py` 崩溃版特征(`test123` / `args or {}` / `params or {}` / `dict(params or {})`)0 命中 + `ast.parse` 通过 |
|
||||
> | V3 | `projects/{项目}/env/test.json` 的 `db.sandbox` 段齐备(`scope=sandbox_only` + `sandbox_schema` + host/port/user/password)——凭据唯一事实源在 env,代码内零明文 |
|
||||
> | V4 | `docs/02-develop` 三份运行证据日志齐备,harness 日志含 C-3.1~C-3.4 全 `[PASS]` 与 IDM.6 的 `1062 Duplicate entry ... uk_ev_dedup` 真防重原文,且无裸 `Traceback` |
|
||||
> | V5 | 工作空间根一次性产物卫生:`tmp_*.py` / `_scratch_*.py` / `*_patch.py` / `*_out.txt` / `*_ev<N>.txt` / `r<N>.txt` / `*.bak` / 根级临时目录全类扫描。**M5a 链路自身产物属反向门禁、不许进白名单,磁盘上一经出现即 FAIL**:`M5A_OWN_DUMP_GONE = ('.scratch_m5a', 'closure_out.txt', 'evidence_raw.txt', 'r1.txt', 'r2.txt')`——收口时其内 git 证据先按字节原样迁到 `projects/pbls/docs/02-develop/m5a-git-closure-evidence-raw.txt`(sha256 一致)再整目录删除,证据不丢、根上不留转储。他链产物必须在 `WS_KEPT` 白名单里**逐项写明引用它的文档路径**,否则 FAIL |
|
||||
> | V5 | 工作空间根一次性产物卫生:`tmp_*.py` / `_scratch_*.py` / `*_patch.py` / `*_out.txt` / `*_ev<N>.txt` / `r<N>.txt` / `*.bak` / 根级临时目录全类扫描。**M5a 链路自身产物属反向门禁、不许进白名单,磁盘上一经出现即 FAIL**:`M5A_OWN_DUMP_GONE = ('.scratch_m5a', 'closure_out.txt', 'evidence_raw.txt', 'r1.txt', 'r2.txt')`——收口时其内 git 证据先按字节原样迁到 `projects/pbls/docs/02-develop/m5a-git-closure-evidence-raw.txt`(sha256 一致)再整目录删除,证据不丢、根上不留转储。他链产物必须在 `WS_KEPT` 白名单里**逐项写明引用它的文档路径**,否则 FAIL。另有 5.1b 防洗白回归门禁:`WS_KEPT` 中一旦出现名字含 `m5a` 的条目即 FAIL(防后人再用「放宽门禁迁就残留产物」这条错路,QC #2 教训固化) |
|
||||
> | V6 | README 声称的 selfcheck 门禁条数 == 代码 `CHECKS` 条数(12) |
|
||||
> | V7 | README 本小节声称的收口条数 == 本脚本 `CHECKS` 条数(7),且脚本路径磁盘命中 |
|
||||
>
|
||||
|
||||
@ -10,17 +10,18 @@ requires-python = ">=3.9"
|
||||
# pbl_common:同机构 modules/ 下的兄弟模块,由宿主 pip install -e 装入,非 PyPI 包,故不声明。
|
||||
dependencies = ["sqlor"]
|
||||
|
||||
# ── 测试依赖(DISC.2:显式声明,禁止靠「宿主恰好装了 pytest」或临时注入 PYTHONPATH)──
|
||||
# 用途:`pip install -e .[test]` 或 `pip install -r requirements-dev.txt` 一次装齐,
|
||||
# 之后 `python3 -m pytest tests/test_m5a_idempotency.py -v` 可直接执行。
|
||||
# 落盘引导脚本:scripts/setup_test_env.sh(建 .venv-test 并装入本 extra)。
|
||||
# ── 测试依赖(发现项 DISC.2)────────────────────────────────────────────
|
||||
# 显式声明 pytest,禁止再靠「宿主 python3 恰好装了 pytest」或临时注入
|
||||
# PYTHONPATH=<workspace>/.pylibs 跑测试(后者会让 test 角色误判为用例失败/环境不可用)。
|
||||
# 用法:pip install -e .[test](等价于 pip install -r requirements-dev.txt),
|
||||
# 或直接 bash scripts/run_tests.sh(自动定位/引导测试环境,见 README「Running tests」)。
|
||||
[project.optional-dependencies]
|
||||
test = ["pytest>=7.0,<10"]
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
# tests/ 用 importlib 隔离加载包(绕过宿主依赖),故不需要额外 pythonpath 注入
|
||||
# tests/test_m5a_idempotency.py 用 importlib 隔离加载包(绕过宿主依赖),
|
||||
# 无需任何 pythonpath 注入;此处不设 addopts,避免干扰命令行 -v 的详细输出。
|
||||
testpaths = ["tests"]
|
||||
addopts = "-q --color=no"
|
||||
|
||||
[build-system]
|
||||
requires = ["setuptools>=61"]
|
||||
|
||||
13
requirements-dev.txt
Normal file
13
requirements-dev.txt
Normal file
@ -0,0 +1,13 @@
|
||||
# pbl_evidence —— 测试前置依赖(发现项 DISC.2:显式声明,不再靠临时注入 PYTHONPATH)
|
||||
#
|
||||
# 与 pyproject.toml 的 [project.optional-dependencies].test 等价,单列一份是为了
|
||||
# 让「不安装本包也能跑离线单测」的场景(CI / 测试机宿主)有一条最短安装命令:
|
||||
# python3 -m pip install -r requirements-dev.txt
|
||||
#
|
||||
# 版本区间与 pyproject test extra 保持一致(>=7.0,<10):
|
||||
# - 下限 7.0:需要 pytest.mark.skipif 条件式与 monkeypatch raising 参数的稳定语义;
|
||||
# - 上限 <10:主版本跳变前不自动跟随,避免解析器/插件接口变更打挂既有 9 条用例。
|
||||
#
|
||||
# 注意:pytest 是**测试**依赖,绝不写进 [project].dependencies——否则宿主
|
||||
# `pip install -e modules/pbl_evidence` 会被拖入无关安装,且违反「只声明直接代码依赖」铁律。
|
||||
pytest>=7.0,<10
|
||||
84
scripts/run_tests.sh
Executable file
84
scripts/run_tests.sh
Executable file
@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env bash
|
||||
# =====================================================================
|
||||
# pbl_evidence 测试运行器(发现项 DISC.2)
|
||||
#
|
||||
# 一条命令跑通离线单测,**不需要手工注入 PYTHONPATH**:
|
||||
# bash scripts/run_tests.sh # 等价 python3 -m pytest tests/test_m5a_idempotency.py -v
|
||||
# bash scripts/run_tests.sh tests/test_m5a_idempotency.py -v
|
||||
# bash scripts/run_tests.sh --log /tmp/m5a-pytest.log
|
||||
# PBL_EVIDENCE_TEST_DB=1 bash scripts/run_tests.sh # 打开真实双次采集用例(需测试库)
|
||||
# PBL_EVIDENCE_TEST_DB=1 PBL_EVIDENCE_TEST_TENANT=m5a-demo bash scripts/run_tests.sh
|
||||
#
|
||||
# 解释器解析顺序(第一个「能 import pytest」的胜出):
|
||||
# ① $PBL_EVIDENCE_TEST_PYTHON —— 显式指定(CI 用宿主 venv 时走这条)
|
||||
# ② 宿主 python3 —— 若已 pip install pytest / -e .[test](正规长期方案)
|
||||
# ③ 模块测试 venv .venv-test/bin/python —— 缺则自动调 scripts/setup_test_env.sh 引导
|
||||
# 全部不可用 → exit 3 并打印可执行的修复命令(不静默跳过、不假绿)。
|
||||
#
|
||||
# 为什么不再用 PYTHONPATH=<workspace>/.pylibs:那是工作空间私有的临时目录,
|
||||
# 换机器/换角色即失效,且把「环境缺依赖」伪装成「测试通过」,属 DISC.2 根因。
|
||||
# =====================================================================
|
||||
set -euo pipefail
|
||||
|
||||
MODULE_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
VENV="${PBL_EVIDENCE_TEST_VENV:-${MODULE_ROOT}/.venv-test}"
|
||||
DEFAULT_TARGET="tests/test_m5a_idempotency.py -v"
|
||||
|
||||
log() { echo "[run_tests] $*"; }
|
||||
die() { echo "[run_tests][FATAL] $*" >&2; exit "${2:-1}"; }
|
||||
|
||||
has_pytest() {
|
||||
local py="$1"
|
||||
[ -x "${py}" ] || return 1
|
||||
"${py}" -c 'import pytest' >/dev/null 2>&1
|
||||
}
|
||||
|
||||
cd "${MODULE_ROOT}"
|
||||
|
||||
# ---- 解析解释器 ----
|
||||
PY=""
|
||||
for cand in "${PBL_EVIDENCE_TEST_PYTHON:-}" "$(command -v python3 || true)" "${VENV}/bin/python"; do
|
||||
[ -n "${cand}" ] || continue
|
||||
if has_pytest "${cand}"; then
|
||||
PY="${cand}"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -z "${PY}" ]; then
|
||||
log "宿主 python3 与测试 venv 均无 pytest,引导测试环境(scripts/setup_test_env.sh)"
|
||||
bash "${MODULE_ROOT}/scripts/setup_test_env.sh" || die "测试环境引导失败,见上方日志" 3
|
||||
PY="${VENV}/bin/python"
|
||||
has_pytest "${PY}" || die "引导后仍无法 import pytest(${PY})" 3
|
||||
fi
|
||||
|
||||
log "python = ${PY} ($("${PY}" -V 2>&1))"
|
||||
log "pytest = $("${PY}" -m pytest --version 2>&1 | head -1)"
|
||||
log "cwd = ${MODULE_ROOT}"
|
||||
[ "${PBL_EVIDENCE_TEST_DB:-}" = "" ] && \
|
||||
log "DB 开关 = 未设置(真实双次采集用例 test_double_collect_is_idempotent_with_db 预期 SKIPPED)" || \
|
||||
log "DB 开关 = PBL_EVIDENCE_TEST_DB=${PBL_EVIDENCE_TEST_DB} tenant=${PBL_EVIDENCE_TEST_TENANT:-m5a-idem-test}"
|
||||
|
||||
# ---- 参数:无参数时用默认目标;--log FILE 把输出同时落盘 ----
|
||||
LOG=""
|
||||
ARGS=()
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--log) LOG="${2:-}"; shift 2 ;;
|
||||
*) ARGS+=("$1"); shift ;;
|
||||
esac
|
||||
done
|
||||
[ ${#ARGS[@]} -gt 0 ] || ARGS=(${DEFAULT_TARGET})
|
||||
|
||||
if [ -n "${LOG}" ]; then
|
||||
mkdir -p "$(dirname "${LOG}")"
|
||||
set +e
|
||||
"${PY}" -m pytest "${ARGS[@]}" 2>&1 | tee "${LOG}"
|
||||
RC=${PIPESTATUS[0]}
|
||||
set -e
|
||||
echo "# RC=${RC}" >> "${LOG}"
|
||||
else
|
||||
"${PY}" -m pytest "${ARGS[@]}"
|
||||
RC=$?
|
||||
fi
|
||||
exit ${RC}
|
||||
54
scripts/setup_test_env.sh
Executable file
54
scripts/setup_test_env.sh
Executable file
@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env bash
|
||||
# =====================================================================
|
||||
# pbl_evidence 测试环境引导(发现项 DISC.2)
|
||||
#
|
||||
# 背景:测试机宿主 python3 **没有** pytest,`python3 -m pytest` 直接
|
||||
# `No module named pytest`。此前靠临时注入
|
||||
# PYTHONPATH=<workspace>/.pylibs(pytest 9.1.1)跑通,属一次性手段,
|
||||
# 不可复现、且会让 test 角色误判为「用例失败/环境不可用」。
|
||||
#
|
||||
# 本脚本把「测试前置依赖」变成显式、可重放的步骤:
|
||||
# 1) 在模块仓库内建独立测试 venv(默认 .venv-test,已在 .gitignore 排除)
|
||||
# 2) 安装 requirements-dev.txt(== pyproject [project.optional-dependencies].test)
|
||||
# 3) 打印 pytest 版本自证可用
|
||||
#
|
||||
# 用法:
|
||||
# bash scripts/setup_test_env.sh
|
||||
# PBL_EVIDENCE_TEST_VENV=/tmp/ev-venv bash scripts/setup_test_env.sh # 换 venv 位置
|
||||
# PBL_EVIDENCE_INSTALL_PKG=1 bash scripts/setup_test_env.sh # 顺带 pip install -e .
|
||||
#
|
||||
# 幂等:venv 已存在则复用,pip 已满足则秒退;可被 build.sh / CI 反复调用。
|
||||
# =====================================================================
|
||||
set -euo pipefail
|
||||
|
||||
MODULE_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
VENV="${PBL_EVIDENCE_TEST_VENV:-${MODULE_ROOT}/.venv-test}"
|
||||
REQ_DEV="${MODULE_ROOT}/requirements-dev.txt"
|
||||
HOST_PY="${PBL_EVIDENCE_HOST_PYTHON:-$(command -v python3)}"
|
||||
|
||||
log() { echo "[setup_test_env] $*"; }
|
||||
die() { echo "[setup_test_env][FATAL] $*" >&2; exit 1; }
|
||||
|
||||
[ -f "${REQ_DEV}" ] || die "缺少测试依赖清单 ${REQ_DEV}"
|
||||
[ -x "${HOST_PY}" ] || die "找不到宿主 python3(可用 PBL_EVIDENCE_HOST_PYTHON 指定)"
|
||||
|
||||
if [ ! -x "${VENV}/bin/python" ]; then
|
||||
log "创建测试 venv: ${VENV}"
|
||||
"${HOST_PY}" -m venv "${VENV}" || die "python3 -m venv 失败(宿主缺 venv 模块?)"
|
||||
else
|
||||
log "复用已存在的测试 venv: ${VENV}"
|
||||
fi
|
||||
|
||||
VPY="${VENV}/bin/python"
|
||||
# 升级 pip 属尽力而为(离线/内网源可能不可达),失败不阻断——真正的门禁是下一步安装
|
||||
"${VPY}" -m pip install --quiet --upgrade pip >/dev/null 2>&1 || log "pip 自升级跳过(不影响后续安装)"
|
||||
log "安装测试依赖: ${REQ_DEV}"
|
||||
"${VPY}" -m pip install -r "${REQ_DEV}" || die "安装 pytest 失败:检查内网 PyPI 源可达性(见 README「Running tests」排障)"
|
||||
|
||||
if [ "${PBL_EVIDENCE_INSTALL_PKG:-0}" = "1" ]; then
|
||||
log "安装模块本体(可编辑):pip install -e ${MODULE_ROOT}"
|
||||
"${VPY}" -m pip install -e "${MODULE_ROOT}" || die "pip install -e . 失败"
|
||||
fi
|
||||
|
||||
log "自证可用:$("${VPY}" -m pytest --version 2>&1 | head -1)"
|
||||
log "TEST ENV READY: ${VPY}"
|
||||
Loading…
x
Reference in New Issue
Block a user