97 lines
4.1 KiB
Bash
Executable File
97 lines
4.1 KiB
Bash
Executable File
#!/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
|
||
#
|
||
# 想在当前 shell 里**原样**敲 `python3 -m pytest ...`(任务要求的字面命令):
|
||
# source scripts/activate_test_env.sh && python3 -m pytest tests/test_m5a_idempotency.py -v
|
||
#
|
||
# 解释器解析顺序(第一个「能 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}"
|
||
|
||
# ---- 仓库卫生自检(QC #1 回归防线,不阻断测试,只打印)----
|
||
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||
_hyg="$(git check-ignore -q "${VENV#${MODULE_ROOT}/}" && echo ignored || echo NOT-ignored)"
|
||
_trk="$(git ls-files "${VENV#${MODULE_ROOT}/}" | wc -l | tr -d ' ')"
|
||
log "仓库卫生: .gitignore=${_hyg} tracked_in_venv=${_trk}(期望 ignored / 0)"
|
||
[ "${_hyg}" = "ignored" ] || log "[WARN] venv 落点未被 .gitignore 忽略,会把依赖目录提交进版本库"
|
||
[ "${_trk}" = "0" ] || log "[WARN] venv 内有 ${_trk} 个文件仍被版本跟踪,执行 git rm -r --cached '${VENV#${MODULE_ROOT}/}'"
|
||
fi
|
||
|
||
# ---- 解析解释器 ----
|
||
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}
|