OpenMed 测试体系实战:测试分层、CI 基线命令与 Zero-Shot 冒烟验证

发布时间:2026/9/18 7:43:25
OpenMed 测试体系实战:测试分层、CI 基线命令与 Zero-Shot 冒烟验证 OpenMed 测试体系实战测试分层、CI 基线命令与 Zero-Shot 冒烟验证【免费下载链接】openmedLocal-first healthcare AI: clinical NER HIPAA PII de-identification that runs 100% on-device. 2,200 medical models, 21 languages, Apple MLX Python, no cloud, no patient data leaving your network. Apache-2.0项目地址: https://gitcode.com/GitHub_Trending/ope/openmedOpenMed 是一个本地优先local-first的临床 NER 与 HIPAA PII 脱敏工具库其测试体系围绕离线可运行、快速回归、可复现 CI三个目标构建。本篇基于 docs/testing.md 的官方指引结合 pyproject.toml 中的 pytest 配置、Makefile 质量门禁与 tests/run-tests.sh 基线脚本系统讲解 OpenMed 的测试分层unit / integration / slow、完整运行命令、GLiNER zero-shot 冒烟检查参数以及文档与 API 一致性校验方法。读完后你可以直接在本仓库中复现整套测试与冒烟流程并为新特性补充符合项目规范的测试。测试体系总览官方文档 docs/testing.md 的开篇定位很明确借助现有的测试套件与冒烟脚本让回归问题远离你的临床工作流。整个测试资产分布在tests/目录下按 tests/README.md 的说明组织如下tests/unit/—— 快速、隔离的单元测试覆盖配置、模型加载辅助函数、分词、格式化与工具模块tests/integration/—— 更高层的场景测试通过 mock 的 transformers pipeline 验证analyze_text、list_models等公共 API 表面tests/fixtures/—— 共享样例文本与可复用的 pytest fixturestests/conftest.py—— 全局 fixture负责 mock transformers 组件、配置重置与样例数据。关键设计决策是重度 mock 下游 Hugging Face APItransformer 层在测试期间被打补丁patched但transformers包本身仍必须可导入因此安装时需要pip install transformers可选安装torch作为 CPU 后端。这使得捆绑测试完全不需要网络访问即可运行——一旦测试失败问题要么指向 OpenMed 代码的回归要么指向本地依赖缺失排障边界清晰。测试标记Marker分类docs/testing.md 给出的测试分类表如下标记位置用途unit默认tests/unit/**对模型注册表辅助函数、配置工具与核心 API 的快速验证integration显式选择opt-in演练多组件流程如 pipeline 创建 formatterslow显式选择opt-in运行较重的 GLiNER 或 Hugging Face 调用除非传入-m slow否则禁用文档指出这些标记通过 pyproject.toml 中的pytest.ini条目即[tool.pytest.ini_options]来配置。仓库中该配置块的实际内容比文档表格更丰富除了文档提到的integration与slow之外还定义了契约与模糊测试标记以及测试文件匹配规则与测试路径[tool.pytest.ini_options] markers [ integration: marks end-to-end or external integration tests, slow: marks tests that are expected to run slowly, contract: marks property-based stage-boundary contract tests, fuzz: marks property-based (Hypothesis) fuzz tests, doctest_examples: runs doctest examples for targeted public modules ] python_files [ test_*.py, *_test.py, ] testpaths [ tests, ]从源码结构看标记在测试代码中通过pytest.mark.marker声明。例如 tests/integration/test_end_to_end.py 中的TestEndToEndAnalysis使用pytest.mark.integration标注并同时 patchopenmed.core.backends._module_available、openmed.core.models.pipeline、AutoConfig、AutoTokenizer、AutoModelForTokenClassification等 HF 组件再驱动analyze_text全流程——这正是文档表格中pipeline 创建 formatter 组合类集成流程的真实示例。仓库中同时标注了integration与slow双标记的文件如 tests/integration/test_distroless_image.py、tests/mobile/test_flutter_ffi.py则会同时受两层选择条件约束。运行完整测试套件docs/testing.md 给出的标准运行流程是uv pip install .[dev,hf] make lint make format-check make lint-swift # 用于 Swift/OpenMedKit 变更 pytest # 快速的 unit/integration 混合 pytest -m not slow # 默认行为 pytest -m slow # 仅运行长耗时用例这些命令与 Makefile 中的目标一一对应理解各目标的具体实现有助于排查失败make lint—— 实际执行uv run --frozen --extra dev ruff check .即基于锁定的 uv 开发环境运行 Ruff 静态检查make format-check—— 执行uv run --frozen --extra dev ruff format --check .只检查不修改文件make lint-swift—— 调用 scripts/lint_swift.sh对swift/OpenMedKit等 Swift 侧代码做格式 lint仅在你改动了 Swift/OpenMedKit 时需要make test—— 执行uv run --frozen --extra dev pytest与裸pytest等效但复现性更强锁定依赖解析make quality—— 组合门禁lint type-check format-check test适合作为本地提交前的完整质量关卡另外pyproject.toml 中 Ruff 的 lint 规则为E9、F63、F7、F82、I目标版本py310行宽 88并排除examples/notebooks与openmed/service/proto/generated。tests/run-tests.shCI 基线脚本docs/testing.md 特别强调tests/run-tests.sh把 lint、格式检查、单元测试与慢速冒烟检查串在一起应作为 CI 的基线。查看 tests/run-tests.sh 的完整实现它按以下顺序执行#!/usr/bin/env bash set -euo pipefail python3 -m venv .venv source .venv/bin/activate python -m pip install --upgrade pip /tmp/pip-up.log pip install -e .[dev] /tmp/pip-install.log ruff check . ruff format --check . # Core test suite without slow markers (collect coverage for zero-shot modules) pytest -m not slow --covopenmed/ner --cov-reportterm-missing # Zero-shot slow checks (gracefully skip when dependencies unavailable) pytest -m slow其中有三个值得注意的细节set -euo pipefail保证任何一步失败立即终止避免假绿核心套件显式指定--covopenmed/ner即对 zero-shot NER 模块单独收集覆盖率终端缺失行报告这与 OpenMed 将 zero-shot 能力列为核心特性之一的定位一致pytest -m slow位于脚本末尾慢速检查在依赖不可用时优雅跳过gracefully skip不会阻塞主流程。若不需要脚本、只想手动分层运行tests/README.md 给出了等效命令# 全量unit integration pytest # 仅轻量单元测试 pytest tests/unit pytest -m not integration # 仅集成场景 pytest -m integration # 生成覆盖率报告 pytest --covopenmed --cov-reportterm-missingGLiNER Zero-Shot 冒烟检查对于 zero-shot 场景docs/testing.md 建议的冒烟命令是uv pip install .[gliner] python scripts/smoke_gliner.py --limit 2 --threshold 0.4 --adapterscripts/smoke_gliner.py 是一个独立的命令行冒烟运行器其参数与行为在源码中都有明确定义可结合参数注释逐一理解参数默认值作用--index打包内置索引指定models/index.json的路径缺省时使用包内模型索引--limit3限制被测 GLiNER 模型数量--threshold0.4实体置信度阈值--adapter关闭flag推理后运行 token classification 适配器输出 BIO/BILOU 标签脚本的源码级执行链路为先通过is_gliner_available()检查依赖缺失时直接报错并提示pip install .[gliner]然后load_index()加载模型索引并筛选出family ModelFamily.GLINER的记录对每个被选中的模型按其第一个 domain 从DEFAULT_SAMPLE_TEXTS中选取领域样例文本覆盖 biomedical、clinical、genomic、finance、legal 等 15 个领域如 biomedical 域的 Imatinib inhibits BCR-ABL in chronic myeloid leukemia patients.构造NerRequest(model_id..., text..., threshold..., domain...)后调用infer()执行推理每个实体以- label: text [start-end] scorescore的格式打印。若传入--adapter再调用to_token_classification(response.entities, request.text)把实体结果转换为 token 级标注TokenClassificationResult逐 token 打印标签——这条链路同时验证了推理与 BIO/BILOU 转换两个环节正好对应后文覆盖建议中提到的 zero-shot 适配器测试点。文档与 API 一致性检查docs/testing.md 还给出两类套件之外的检查1. 文档构建检查——在 CI 中加入uv run mkdocs build --strict让缺失的导航条目、重复锚点或损坏的 markdown 直接导致构建失败。仓库中 Makefile 的docs-serve本地 127.0.0.1:8008 热重载与docs-build/docs-stage目标构建并暂存最终 Pages 产物到site/提供了本地对照手段。2. 轻量 API 冒烟测试——确保打包与 extras 保持同步的最小示例from openmed import analyze_text result analyze_text(QA ping, model_namedisease_detection_superclinical) assert result.entities is not None这个 snippet 的价值在于它同时验证了打包完整性openmed可导入、模型注册表条目disease_detection_superclinical是合法model_name与核心 API 返回结构result.entities非空。新增功能时的覆盖建议清单docs/testing.md 结尾给出的四项覆盖建议结合仓库现有测试资产可以落地为具体做法模型注册表条目——确保新模型键出现在list_model_categories中。可在tests/unit下补充断言新键的分类归属参照 tests/integration/test_end_to_end.py 中对list_models的调用方式公共 API 选项与默认行为——验证analyze_text等入口的参数默认值与行为契约Formatter 行为HTML/CSS 属性、元数据传播——单元测试 formatter 的输出属性与元数据透传Zero-shot 适配器BIO/BILOU 转换——即scripts/smoke_gliner.py中--adapter路径所覆盖的to_token_classification转换逻辑。编写这些测试时可直接复用 tests/conftest.py 提供的全局 fixture例如sample_text/sample_long_text—— 短、长两档临床样例文本mock_pipeline/sample_predictions—— 预置了B-CONDITIONdiabetes, score 0.95、B-MEDICATIONmetformin, score 0.89、B-DOSAGE500mg等 BIO 标签预测结果的 mock pipeline使 NER 后处理逻辑可以完全离线断言mock_tokenizer—— 带offset_mapping、word_ids()的 mock tokenizer用于验证 span 对齐sample_config—— 基于OpenMedConfig的测试配置devicecpu、缓存目录指向/tmp。小结OpenMed 的测试实践可以浓缩为一条本地工作流# 安装开发依赖并运行质量门禁 make quality # lint type-check format-check test # 或以 CI 基线脚本方式一键执行含 zero-shot 覆盖率 bash tests/run-tests.sh # zero-shot 冒烟需要 [gliner] extras uv pip install .[gliner] python scripts/smoke_gliner.py --limit 2 --threshold 0.4 --adapter遵循 docs/testing.md 的分类表、tests/run-tests.sh 的 CI 基线以及上文覆盖建议清单可以让新增代码的文档保持准确、自动化流水线保持绿色这也是该项目离线优先、可复现工程哲学在质量保障层面的直接体现。【免费下载链接】openmedLocal-first healthcare AI: clinical NER HIPAA PII de-identification that runs 100% on-device. 2,200 medical models, 21 languages, Apple MLX Python, no cloud, no patient data leaving your network. Apache-2.0项目地址: https://gitcode.com/GitHub_Trending/ope/openmed创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考