
用 nf-test 为 Nextflow 与 nf-core 组件构建可靠测试模块、子工作流与流水线的测试全指南【免费下载链接】scientific-agent-skillsTurn any AI agent into an AI Scientist. The #1 Agent Skills library for science, used by 190,000 scientists worldwide. 165 ready-to-use validated skills plus 100 scientific databases covering biology, chemistry, medicine, and drug discovery. Compatible with Cursor, Claude Code, Codex, Pi, Antigravity, and the open Agent Skills standard.项目地址: https://gitcode.com/GitHub_Trending/cl/scientific-agent-skillsnf-test 是 Nextflow 生态的标准测试框架也是 nf-core 社区对每个模块module、子工作流subworkflow和流水线pipeline的强制测试要求。本文以 scientific-agent-skills 仓库中 Nextflow 技能 的测试参考文档为核心系统讲解 nf-test 的安装初始化、测试文件结构、三种测试作用域process/workflow/pipeline、断言与快照测试的完整写法并结合仓库内 developing.md 与 nf-core-tools.md 的源码级约定给出可复制、可运行、可直接进入 CI 的实战方案。读完后你将能够独立为任意 Nextflow 模块编写并维护 nf-test 测试套件并通过 nf-core 工具链完成测试、lint 与 CI 集成。为什么是 nf-testNextflow 测试的行业标准Nextflow 是一个用于构建可复现、可移植、可扩展数据流水线的工作流语言与运行时在生物信息学领域占据主导地位同时适用于任何数据密集型计算详见 SKILL.md 的 Overview。nf-core 则是建立在 Nextflow 之上的社区负责维护生产级流水线、可复用模块以及nf-core工具链。在这样一个以复用与标准化为核心的生态里测试不再是可选项nf-test 是 Nextflow 的标准测试框架nf-core 要求每个模块、子工作流和流水线都必须具备 nf-test 覆盖。这意味着模块作者提交代码前必须提供可运行的 nf-test 测试含 stub 测试并提交快照snapshot文件nf-core modules lint会校验测试文件是否齐备CI 中通过--changed-since只对变更组件执行测试保证每次合并的可靠性。本指南对应的核心文档位于 skills/nextflow/references/testing.md是 Nextflow 技能体系中负责测试的独立自洽章节。安装与初始化Setupnf-test 的安装方式有两种任选其一# 方式一通过 conda/bioconda 安装 conda install -c bioconda nf-test # 方式二官方安装脚本自包含 curl -fsSL https://get.nf-test.com | bash安装完成后在项目根目录执行初始化nf-test init # 创建 nf-test.config tests/ 脚手架nf-test init会在项目中生成两个关键产物nf-test.config集中设置测试目录、默认 profile 和插件tests/脚手架测试文件的组织目录。测试文件的命名与位置遵循严格约定测试文件以.nf.test结尾测试文件放在被测组件旁边例如tests/main.nf.test在 nf-core 组件目录下则为modules/nf-core/tool/subtool/tests/main.nf.test期望结果存储在同级的.nf.test.snap快照文件中例如tests/main.nf.test.snap。从 developing.md 的模块目录解剖可以看到 nf-core 的标准布局测试是模块不可分割的一部分modules/nf-core/samtools/sort/ ├── environment.yml # Conda channels 固定版本依赖 ├── main.nf # 被测 process ├── meta.yml # 记录 I/O 接口 工具信息schema 校验 └── tests/ ├── main.nf.test # nf-test 测试必需且必须包含 stub 测试 └── main.nf.test.snap测试文件结构三种作用域.nf.test文件用 Groovy 编写外层作用域scope决定了测试对象共有三种作用域测试对象说明nextflow_process单个 process/模块最常用直接驱动一个模块nextflow_workflow子工作流测试由多个模块组成的 (sub)workflownextflow_pipeline整条流水线驱动整个main.nf一个典型的nextflow_process测试文件结构如下以 SAMTOOLS_SORT 为例nextflow_process { name Test SAMTOOLS_SORT script ../main.nf // 被测模块 process SAMTOOLS_SORT tag modules tag modules_nfcore tag samtools tag samtools/sort test(sarscov2 - bam) { when { process { input[0] [ [ id:test, single_end:false ], file(params.modules_testdata_base_path genomics/sarscov2/illumina/bam/test.bam, checkIfExists: true) ] } } then { assertAll( { assert process.success }, { assert snapshot(process.out).match() } ) } } }关于该结构的几个关键点input[0]、input[1]、…按位置绑定 process 的输入通道tag用于为测试打标签既可按主题分组samtools也支持精确到组件samtools/sort配合--tag参数可筛选运行setup { }块可以运行前置 process 来产出输入见下文测试模块一节params { }块设置参数config ...行为测试加载指定配置nf-core 强制要求真实测试之外还要有一个 stub 测试——在test(...)块内添加options -stub即可驱动模块的stub:脚本来做管道冒烟验证。关于 meta map元数据映射的约定也值得注意nf-core 约定在输入/输出元组中携带[ id:test, single_end:false ]这样的元数据 map且 meta 永远是元组的第一个元素见 developing.md 的 The meta map convention。测试中的input[0]直接遵循了这一约定。测试模块process测试一个模块的核心是when/then两段式结构when块供应输入then块对结果进行断言。当被测模块需要另一个模块的输出作为输入时使用setup块先运行前置模块test(sort then index) { setup { run(SAMTOOLS_SORT) { script ../../sort/main.nf process { input[0] [ [id:test], file(params.test_data test.bam, checkIfExists:true) ] } } } when { process { input[0] SAMTOOLS_SORT.out.bam } } then { assert process.success assert snapshot(process.out).match() } }在这个例子中setup块通过run(SAMTOOLS_SORT)执行排序模块用script指向其main.nf并为其绑定输入when块把SAMTOOLS_SORT.out.bam命名输出通道直接作为被测 process 的input[0]then块断言成功并比对快照。when块中也可以混用直接赋值与通道引用例如某模块的输入部分来自手工构造的元组、部分来自上游通道。这种先 setup 产出、再 when 消费的模式正是 nf-test 对有依赖链的模块的标准测试手法。断言Assertionsthen块内的断言决定了测试的判定逻辑。当有多个检查项时务必用assertAll(...)包裹这样所有失败会一次性全部报告而不是在第一个失败处中断。常用断言句柄与辅助函数表达式检查内容process.success/process.failed任务成功 / 失败process.exitStatus 0退出码process.out.emit某个命名输出通道的内容process.out.bam.get(0)第一个发射的元素workflow.success、workflow.trace.tasks().size()工作流结果 / 任务数量path(process.out.bam[0][1]).exists()某个文件是否存在snapshot(...).match()与存储的快照比对assertContainsInAnyOrder(ch, [...])通道包含给定元素不要求顺序两个容易踩坑的要点没有assertContainsInOrder。如果需要对文件内容做有序或子串检查直接读取行内容再断言例如assert path(out[0][1]).readLines().any { it.contains(Done) } assert path(out[0][1]).readLines().last().contains(completed)插件plugins可以扩展领域相关的断言能力例如nft-bamBAM 文件、nft-vcfVCF 文件、nft-utils通用工具。nf-core 会在nf-test.config中启用这些插件。一个带文件内容断言与插件快照的完整示例then { assertAll( { assert process.success }, { assert path(process.out.bam[0][1]).exists() }, { assert snapshot( bam(process.out.bam[0][1]).getSamLinesMD5(), process.out.versions ).match() } ) }这里bam(...).getSamLinesMD5()来自nft-bam插件对 BAM 解析出的 SAM 行计算 MD5将其与versions.yml一起纳入快照比对——既验证了二进制产物内容稳定又验证了版本报告正确。关于版本报告developing.md 指出当前主流的versions.yml模式通过 HEREDOC 写入并作为path versions.yml, emit: versions输出nf-core modules create新生成的模块则改用 topic 通道 eval()捕获版本。无论哪种模式模块必须 emit 版本通道且测试中应纳入快照这正是上例快照中包含process.out.versions的原因。快照测试Snapshot Testing快照测试是 nf-test 最核心的回归保护机制snapshot(x).match() // 序列化 x 并与 .nf.test.snap 文件比对首次运行会记录快照生成.nf.test.snap此后每次运行若输出发生变化测试即失败。这实现了一次编写持续防回归。使用快照的三条黄金法则只快照稳定内容文件 MD5/校验和、versions.yml、列表长度等绝不快照绝对路径或时间戳它们每次运行都会变导致虚假失败有意的变更用命令重新生成快照nf-test test --update-snapshot一个测试内可命名多个快照.match(bam)、.match(versions)分别命名便于多产物分别追踪。快照文件.nf.test.snap需要提交进仓库。nf-core 要求每个模块/子工作流提交通过的快照nf-core modules lint会检查其存在性——详见下文nf-core 集成。测试工作流与流水线对于整条流水线使用nextflow_pipeline作用域直接驱动main.nfnextflow_pipeline { name Test full pipeline script ../main.nf test(default params) { when { params { outdir $outputDir; input tests/samplesheet.csv } } then { assert workflow.success assert workflow.trace.succeeded().size() 0 } } }关键差异与要点when块内通过params { }注入流水线参数$outputDir是 nf-test 提供的自动输出目录变量then块断言workflow.success整个流水线成功以及workflow.trace.succeeded().size() 0确有任务成功完成nextflow_workflow作用域介于两者之间用于测试子工作流包含多个模块的复用单元其写法与nextflow_pipeline相似但script指向子工作流的main.nf。测试数据要小优先从 nf-core/test-datasets 选取微型输入例如nf-core test-datasets search term # 在 nf-core/test-datasets 中查找小型测试文件小数据意味着测试运行快、依赖少可以频繁在 CI 中执行。这也呼应了 SKILL.md 中Alwaystestfirst的最佳实践——用-profile test,docker在真实数据之前先验证环境与管道。运行测试命令全览nf-test 的 CLI 支持从全量运行到单文件/单标签/变更集的精细控制nf-test test # 运行全部测试 nf-test test modules/nf-core/samtools/sort/ # 运行某个目录下的测试 nf-test test tests/main.nf.test # 运行单个测试文件 nf-test test --tag samtools # 按标签筛选配合文件内 tag 声明 nf-test test --profile docker # 选择容器引擎 nf-test test --update-snapshot # 接受新快照重新生成 .nf.test.snap nf-test test --changed-since HEAD^ # 只测试自某次提交以来变更的组件 nf-test test --only-changed --ci # CI 模式缺失快照时失败而不是写入各参数的作用--profile指定执行 profile如docker、singularity、conda与 Nextflow 的 profile 机制对接--update-snapshot用于接受因有意变更而失效的快照--changed-since ref只运行自该 ref 以来发生变更的组件大幅缩短 CI 耗时--only-changed --ci是 CI 专用组合如果快照缺失测试失败而不是自动写入——防止 CI 静默生成未审查的快照。nf-test.config在其中承担三项核心职责设置测试目录、默认 profile、启用插件nf-core 在此启用nft-bam/nft-vcf/nft-utils等。CI 的典型形态只跑变更组件--changed-since--only-changed配合 nf-core 官方提供的 nf-test GitHub Action 完成集成。这样每次 PR 只验证相关模块快且准。nf-core 集成用包装命令管理测试在 nf-core 生态中优先使用nf-core工具的包装命令而不是直接调用nf-test因为包装命令自动携带正确的 profiles、标签和快照处理逻辑nf-core modules create mytool # 脚手架自动生成 tests/main.nf.test 等文件 nf-core modules test mytool # 运行该模块的 nf-test 套件 nf-core subworkflows test mysubwf对应关系详见 nf-core-tools.md命令作用nf-core modules create [tool]脚手架新模块main.nf、meta.yml、tests/nf-core modules test tool运行模块的 nf-test 套件nf-core modules lint tool按模块规范 lint校验测试文件与快照存在性nf-core subworkflows create/test/lint子工作流的同生命周期管理nf-core 的硬性要求总结如下来自 testing.md 与 developing.md每个 nf-core 模块/子工作流必须附带通过的 nf-test 测试测试必须包含一个stub 测试用options -stub驱动stub:脚本快照.nf.test.snap必须提交进仓库nf-core modules lint会检查这些测试产物的存在性不满足则 lint 失败。从 developing.md 的模块解剖可知stub:块在模块中同样是被强制要求的每个输出通道至少要touch出一个文件gzip 输出则用echo | gzip x.gz。stub 测试因此能以近乎零成本的方式验证管道连接是否正确——这正是stub 测试必须与真实测试并存的设计初衷。测试驱动的 nf-core 开发闭环把以上内容串成一个完整的开发工作流融合 nf-core-tools.md 的典型开发循环nf-core pipelines create # 脚手架流水线自带 test profile 与 CI nf-core modules install fastqc # 优先复用社区模块 nf-core modules create mytool # 新增自定义模块自动生成测试脚手架 nf-core modules test mytool # 编写并运行 nf-test真实 stub 测试 nf-core test-datasets search term # 为测试挑选微型数据 nf-core modules lint mytool # 校验测试文件与快照齐备 nf-core pipelines lint # 流水线级 lint prettier --write . # 格式化Harshil 对齐风格随后在 CI 中通过--changed-since--only-changed只验证变更组件配合 nf-core 的 nf-test GitHub Action 完成自动回归。这样从模块脚手架、测试编写、lint 校验到 CI 集成的整条链路都由工具保障——这也是 nf-test 成为 Nextflow 生态唯一标准测试框架的根本原因。小结nf-test 通过nextflow_process/nextflow_workflow/nextflow_pipeline三种作用域覆盖了 Nextflow 组件的全部测试层次模块测试用when/then驱动、setup链式组装、assertAll聚合断言、快照机制防回归、-stub冒烟验证管道、--changed-since支撑高效 CI。结合 nf-core 工具链的create/test/lint生命周期与强制提交快照的规范你可以把测试从一个事后动作变成组件开发的内置环节。本文对应的完整技能入口位于 skills/nextflow/SKILL.md更深入的内容可继续阅读同目录下的 language.mdDSL2 语言、developing.mdnf-core 组件开发规范与 nf-core-tools.mdnf-core CLI 完整参考。【免费下载链接】scientific-agent-skillsTurn any AI agent into an AI Scientist. The #1 Agent Skills library for science, used by 190,000 scientists worldwide. 165 ready-to-use validated skills plus 100 scientific databases covering biology, chemistry, medicine, and drug discovery. Compatible with Cursor, Claude Code, Codex, Pi, Antigravity, and the open Agent Skills standard.项目地址: https://gitcode.com/GitHub_Trending/cl/scientific-agent-skills创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考