Help us improve
Share bugs, ideas, or general feedback.
From nf-core
Runs and manages nf-test for Nextflow pipelines and modules: process tests, snapshot testing, stub runs, pipeline validation, and debugging failures.
npx claudepluginhub jonasscheid/claude-nfcore-pluginHow this skill is triggered — by the user, by Claude, or both
Slash command
/nf-core:nf-testThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Run and manage tests using nf-test for Nextflow pipelines and modules.
Manages nf-core Nextflow pipelines: create new pipelines, lint with strict syntax checks, build/validate/lint schemas, sync templates, run tests, and release. Ensures compliance with nf-core lifecycle and Q2 2026 deadlines.
Builds scalable containerized bioinformatics pipelines with Nextflow dataflow model: processes connected by channels, runnable on local, HPC (SLURM/SGE), cloud (AWS/GCP/Azure), or Kubernetes via config profiles. Powers nf-core pipelines.
Runs Rust tests with cargo-nextest for parallel execution, expression-based filtering, flaky test retries, and CI-optimized configuration.
Share bugs, ideas, or general feedback.
Run and manage tests using nf-test for Nextflow pipelines and modules.
Read ${CLAUDE_PLUGIN_ROOT}/shared/conventions.md for nf-core conventions and package manager setup.
Read ${CLAUDE_PLUGIN_ROOT}/shared/test-patterns.md for test templates and patterns.
Replace <cmd> with the configured package manager prefix (see Setup in conventions.md).
<cmd> nf-test test # Run all tests
<cmd> nf-test test tests/modules/fastqc/ # Specific path
<cmd> nf-test test --profile +docker # Add container profile (+ ADDS, no + REPLACES)
<cmd> nf-test test --tag "modules" # Filter by tag
<cmd> nf-test test --update-snapshot # Update snapshots
<cmd> nf-test test --verbose # Verbose output
<cmd> nf-test list # List available tests
nextflow_process {
name "Test Process FASTQC"
script "../main.nf"
process "FASTQC"
tag "modules"
tag "fastqc"
test("Single-end reads") {
when {
process {
"""
input[0] = [
[ id:'test', single_end:true ],
file(params.test_data['sarscov2']['illumina']['test_1_fastq_gz'], checkIfExists: true)
]
"""
}
}
then {
assert process.success
assert snapshot(process.out).match()
}
}
test("Stub run") {
options "-stub"
when {
process {
"""
input[0] = [ [ id:'test' ], file('dummy.fastq.gz') ]
"""
}
}
then {
assert process.success
assert snapshot(process.out).match()
}
}
}
Pipeline tests use nextflow_pipeline (NOT nextflow_workflow) and load params via profiles.
Params are NEVER defined inline — they go in conf/test_XYZ.config.
conf/test_XYZ.config — all test params (inputs, flags, resources)nextflow.config profiles — test_XYZ { includeConfig 'conf/test_XYZ.config' }nf-test.config — profile "test" as defaulttests/nextflow.config — shared test data base pathsnextflow_pipeline {
name "Test pipeline"
script "../main.nf"
tag "pipeline"
test("-profile test") {
when {
params {
outdir = "$outputDir"
}
}
then {
def stable_name = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}'])
def stable_path = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore')
assertAll(
{ assert workflow.success },
{ assert snapshot(
removeNextflowVersion("$outputDir/pipeline_info/nf_core_pipeline_software_mqc_versions.yml"),
stable_name,
stable_path
).match() }
)
}
}
}
nextflow_pipeline {
name "Test pipeline"
script "../main.nf"
tag "pipeline"
tag "test_foo"
profile "test_foo"
test("-profile test_foo") {
when {
params {
outdir = "$outputDir"
}
}
then {
def stable_name = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}'])
def stable_path = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore')
assertAll(
{ assert workflow.success },
{ assert snapshot(
workflow.trace.succeeded().size(),
removeNextflowVersion("$outputDir/pipeline_info/nf_core_pipeline_software_mqc_versions.yml"),
stable_name,
stable_path
).match() }
)
}
}
}
nextflow_pipeline for pipeline tests — profile is silently ignored in nextflow_workflow/nextflow_processconf/test_XYZ.config — never inline in nf-test fileoutdir in the when blockprofile "test_XYZ" at nextflow_pipeline level overrides defaulttest("-profile test_XYZ")--profile uses + prefix: --profile +docker adds to test profile; without + replacesnft-utils plugin: For getAllFilesFromDir, removeNextflowVersionthen {
// Snapshot all outputs
assert snapshot(process.out).match()
// Snapshot specific channel
assert snapshot(process.out.bam).match()
// Snapshot with custom name
assert snapshot(process.out.zip).match("fastqc_zip_output")
// Filter non-deterministic content before snapshotting
assert snapshot(path(process.out.log[0][1]).readLines().findAll { !it.startsWith('#') }).match()
}
After --update-snapshot, compare against the reference branch and present a summary table:
| Test | Files | Results | Match |
|---|---|---|---|
| default | 71 = 71 | 252 = 252 | 100% |
Do not dismiss snapshot changes as stochastic — many pipelines use fixed seeds.
assert process.success // Process succeeded
assert process.failed // Process failed (error testing)
assert process.out.html // Output exists
assert process.out.html.size() == 1 // Output count
assert path(process.out.html[0][1]).exists() // File exists
assert path(process.out.html[0][1]).text.contains("FastQC") // Content check
assert path(process.out.bam[0][1]).md5 == 'hash' // MD5 check
assert process.out.result[0][0].id == 'test' // Metadata preserved
For large-data tools, use stub tests:
test("Stub run") {
options "-stub"
when {
process {
"""
input[0] = [ [ id:'test' ], file('dummy.bam') ]
"""
}
}
then {
assert process.success
assert snapshot(process.out).match()
}
}
Requires stub: block in process main.nf — see module template.
config {
testsDir "."
workDir System.getenv("NFT_WORKDIR") ?: ".nf-test"
configFile "tests/nextflow.config"
ignore 'modules/nf-core/**/tests/*', 'subworkflows/nf-core/**/tests/*'
profile "test"
triggers 'nextflow.config', 'nf-test.config', 'conf/test.config', 'tests/nextflow.config', 'tests/.nftignore'
plugins {
load "nft-utils@0.0.3"
}
}
params {
modules_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/modules/data/'
pipelines_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/refs/heads/PIPELINE_NAME'
}
aws.client.anonymous = true
<cmd> nf-test test --verbose tests/path/main.nf.test.nf-test/ for .command.err and .command.log<cmd> nf-test test --update-snapshot tests/path/main.nf.test.nf.test.snap files in git diff