ABI 测试指南

测试数量和覆盖率会随代码变化,当前数字以最新 CI 为准。本文说明测试应该放在哪里、 本地常用哪些命令,以及 CI 会检查什么。

测试结构

层级

位置

用途

外部工具

单元

tests/unit/

核心逻辑、schema、解析器、契约和运行时

集成

tests/integration/

CLI/核心边界、dry-run、golden trace

通常不需要

冒烟

tests/smoke/

真实工具与数值级工作流检查

通常需要

SciPlot

src/abi/sciplot/tests/

schema、渲染器、lint、CLI/API、Unicode 排版

report 依赖

文件名使用 test_<feature>.py,函数名使用 test_<behavior>。行为发生变化时应补上 回归测试。调用外部工具的测试使用 @pytest.mark.smoke@pytest.mark.requires_tools,或同时使用两者。

本地命令

# 主测试集
pytest tests/ -v --tb=short

# 接近 CI、排除外部工具
pytest tests/ src/abi/sciplot/tests/ -v --tb=short \
  --strict-markers -m "not requires_tools"

# 聚焦模块
pytest tests/unit/test_dag_planner.py -q

# 仅真实工具测试
pytest tests/ -v -m requires_tools

# 分支感知的全局门禁
pytest tests/ src/abi/sciplot/tests/ \
  --strict-markers -m "not requires_tools" \
  --cov=src/abi --cov-branch --cov-report=term \
  --cov-report=json:coverage.json --cov-fail-under=75
python scripts/check_module_coverage.py --coverage coverage.json

CI 强制全局 75% 底线,并对高风险模块设置行/分支门禁。持续维护的指南中不要写死 某次测得的百分比或测试数量。

共享 fixtures

tests/conftest.py 当前提供:

  • mock_sample

  • mock_sample_context

  • mock_contract_dict

  • tmp_project

  • 隔离 mamba/resource-root 环境变量的 autouse fixture。

复用 fixture 放在这里。文件系统写入使用 tmp_path,环境变量和全局状态通过 pytest fixture 恢复。

插件契约门禁

每个内置插件必须:

  1. 通过 assert_plugin_contract 检查的 Python 插件协议;

  2. 能加载工具注册表和标准表 schema;

  3. 提供声明式 pipeline_dag.yaml

  4. 为每个外部工具输出声明 contract,或给出带理由的显式豁免;

  5. 提供非空 limitations.yaml

对全部内置插件运行严格 lint:

for plugin in \
  amplicon_16s easymetagenome metagenomic_plasmid metatranscriptomics \
  rnaseq_expression viral_viwrap wgs_bacteria
do
  abi contract-lint --type "$plugin" --strict
done

python scripts/audit_contract_coverage.py

严格模式把 warning 也视为失败,并强制检查缺失/无效/空 limitations 和输出 contract 覆盖。

Golden traces

Golden traces 位于仓库根目录:

golden_traces/
├── amplicon_16s.jsonl
├── metagenomic_plasmid.jsonl
├── metatranscriptomics.jsonl
├── rnaseq_expression.jsonl
└── wgs_bacteria.jsonl

当前覆盖 5 个工作流家族,不是全部 7 个内置插件。运行:

pytest tests/integration/test_golden_traces.py -q

有意修改计划后,应先审查语义 diff,再更新 trace;不能只为让测试通过而重新生成。

冒烟与 benchmark

tests/smoke/test_*_benchmark.py 包含原始 5 个工作流家族的真实工具检查, abi.testing.benchmark 提供通用 expected_assertions.yaml 评估器。当前仓库 checkout 不包含完整的 data/benchmarks/ fixture 树。运行这些测试前,应先确认 数据集、期望断言、工具、数据库和环境变量均已配置。默认 CI 会排除 requires_tools 测试。

EasyMetagenome 与 ViWrap 有契约、dry-run、集成和发布 wheel 冒烟覆盖,但当前 没有与原始 5 个工作流相同形态的仓内数值级 benchmark fixture。

CI 与发布表面

仓库有且仅有 4 个 workflow:

  • ci.yml:Python 3.10–3.13 lint/format/mypy、测试、3.12 覆盖率、严格 contract lint、文档、Compose、包构建、wheel 冒烟和 migration gate;

  • docker.yml:仅手动构建并冒烟测试所选插件或全部插件;显式启用 push 后 才向 registry 发布并生成 provenance/SBOM,RNA-seq 之外为多架构;

  • release.yml:复用 CI 门禁、构建、Twine 检查、干净 wheel 冒烟并创建 GitHub Release;

  • publish-pypi.yml:下载 GitHub Release 的原始产物,通过 PyPI Trusted Publishing 发布。

修改 CI/Docker/构建输入时运行:

pytest tests/unit/test_docker_configuration.py -q
docker compose -f docker/docker-compose.yml config --quiet
python -m build

修改文档时运行:

bash docs/build_docs.sh

提交评审前

Python 变更需要 Ruff、格式、mypy、聚焦 pytest 和受影响集成测试。插件变更还需 严格 contract lint、dry-run 和相关 smoke。Release 变更有额外门禁;Docker 变更需要配置检查,并建议手动构建镜像,详见 开发流程发布指南

在 PR 中记录所有命令和结果。无法运行真实工具、容器或集群检查时,必须明确说明 未验证内容和残余风险。