Skip to content

Commit 30ea18b

Browse files
edmundmillerclaude
authored andcommitted
test: reorganize pipeline scenario tests
1 parent cc5a7ea commit 30ea18b

17 files changed

Lines changed: 392 additions & 82 deletions

File tree

tests/AGENTS.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# tests/
2+
3+
## Layout
4+
Each pipeline-level scenario lives in its own directory:
5+
6+
- `pipeline_api_only/`
7+
- `pipeline_mixed_no_benchmark/`
8+
- `pipeline_benchmark_tarball/`
9+
- `pipeline_benchmark_directory/`
10+
11+
Each scenario directory contains:
12+
- `main.nf.test` — the nf-test scenario
13+
- `main.nf.test.snap` — the snapshot for that scenario
14+
- `AGENTS.md` — scenario-specific guidance for future edits
15+
16+
## Conventions
17+
- One scenario per directory.
18+
- Keep assertions local and explicit rather than heavily abstracted.
19+
- Prefer stable fixture files under `workflows/nf_aggregate/assets/`.
20+
- If routing behavior changes, update the scenario-specific `AGENTS.md` along with the test.
21+
22+
## Running tests
23+
Run all pipeline-level scenario tests with:
24+
25+
```bash
26+
find tests -name 'main.nf.test' | sort | xargs nf-test test --profile=+docker --verbose
27+
```

tests/default.nf.test

Lines changed: 0 additions & 57 deletions
This file was deleted.

tests/pipeline_api_only/AGENTS.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# pipeline_api_only
2+
3+
## Purpose
4+
Covers the API-only input path when `generate_benchmark_report` is disabled.
5+
6+
## Fixtures
7+
- `workflows/nf_aggregate/assets/test_run_ids.csv`
8+
9+
## Expected behavior
10+
- No Nextflow processes should run.
11+
- A warning should explain that API runs produce no output without benchmark generation.
12+
- Only `pipeline_info/collated_software_versions.yml` should be emitted.
13+
- No `benchmark_report/` directory should exist.
14+
15+
## Edit guidance
16+
If you change API-only routing, benchmark gating, or warning text, update this test first.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
def INPUT_PATH = new File('workflows/nf_aggregate/assets/test_run_ids.csv').canonicalPath
2+
3+
def expectedOutputNames = [
4+
'pipeline_info',
5+
'pipeline_info/collated_software_versions.yml',
6+
]
7+
8+
def collatedVersions = { outdir ->
9+
new File("${outdir}/pipeline_info/collated_software_versions.yml").text
10+
}
11+
12+
nextflow_pipeline {
13+
name "Pipeline API-only without benchmark"
14+
script "../../main.nf"
15+
tag "pipeline"
16+
tag "nf-aggregate"
17+
tag "api-only"
18+
19+
test("api-only input skips benchmark work") {
20+
tag("test")
21+
22+
when {
23+
params {
24+
input = INPUT_PATH
25+
outdir = "$outputDir"
26+
}
27+
}
28+
29+
then {
30+
def versions = collatedVersions(params.outdir)
31+
def stdout = workflow.stdout.join('\n')
32+
33+
assert workflow.success
34+
assert workflow.trace.succeeded().size() == 0
35+
assert !stdout.contains('Invalid method invocation')
36+
assert stdout.contains('Found 3 API run(s) but --generate_benchmark_report is not enabled.')
37+
assert versions.contains('Workflow:')
38+
assert !versions.contains('EXTRACT_TARBALL:')
39+
assert !versions.contains('BENCHMARK_REPORT:')
40+
assert !new File("${params.outdir}/benchmark_report").exists()
41+
42+
assert snapshot(
43+
workflow.trace.succeeded().size(),
44+
removeFromYamlMap("$outputDir/pipeline_info/collated_software_versions.yml", "Workflow"),
45+
expectedOutputNames
46+
).match()
47+
}
48+
}
49+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"api-only input skips benchmark work": {
3+
"content": [
4+
0,
5+
{
6+
7+
},
8+
[
9+
"pipeline_info",
10+
"pipeline_info/collated_software_versions.yml"
11+
]
12+
],
13+
"meta": {
14+
"nf-test": "0.9.2",
15+
"nextflow": "26.03.1"
16+
},
17+
"timestamp": "2026-04-06T21:16:01.182514"
18+
}
19+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# pipeline_benchmark_directory
2+
3+
## Purpose
4+
Covers benchmark generation when external logs are provided as an already-extracted directory.
5+
6+
## Fixtures
7+
- `workflows/nf_aggregate/assets/test_benchmark_directory.csv`
8+
- JSON fixture directory under `workflows/nf_aggregate/assets/log_dirs/`
9+
10+
## Expected behavior
11+
- `EXTRACT_TARBALL` must not run.
12+
- `BENCHMARK_REPORT` should consume the directory directly.
13+
- Benchmark outputs should include both HTML and DuckDB artifacts.
14+
- The rendered HTML should mention the expected run ID and group.
15+
16+
## Edit guidance
17+
If you change support for directory-based external logs, update this test first.
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
def INPUT_PATH = new File('workflows/nf_aggregate/assets/test_benchmark_directory.csv').canonicalPath
2+
3+
def expectedOutputNames = [
4+
'benchmark_report',
5+
'benchmark_report/benchmark.duckdb',
6+
'benchmark_report/benchmark_report.html',
7+
'pipeline_info',
8+
'pipeline_info/collated_software_versions.yml',
9+
]
10+
11+
def collatedVersions = { outdir ->
12+
new File("${outdir}/pipeline_info/collated_software_versions.yml").text
13+
}
14+
15+
nextflow_pipeline {
16+
name "Pipeline benchmark from directory logs"
17+
script "../../main.nf"
18+
tag "pipeline"
19+
tag "nf-aggregate"
20+
tag "benchmark-directory"
21+
22+
test("benchmark report consumes external log directory directly") {
23+
tag("benchmark")
24+
tag("routing")
25+
26+
when {
27+
params {
28+
input = INPUT_PATH
29+
outdir = "$outputDir"
30+
generate_benchmark_report = true
31+
}
32+
}
33+
34+
then {
35+
def versions = collatedVersions(params.outdir)
36+
def stdout = workflow.stdout.join('\n')
37+
def report = new File("${params.outdir}/benchmark_report/benchmark_report.html")
38+
def database = new File("${params.outdir}/benchmark_report/benchmark.duckdb")
39+
def reportText = report.text
40+
41+
assert workflow.success
42+
assert workflow.trace.succeeded().size() == 1
43+
assert !stdout.contains('Invalid method invocation')
44+
assert !stdout.contains('SEQERALABS_NF_AGGREGATE:NF_AGGREGATE:EXTRACT_TARBALL')
45+
assert stdout.contains('SEQERALABS_NF_AGGREGATE:NF_AGGREGATE:BENCHMARK_REPORT')
46+
assert !versions.contains('EXTRACT_TARBALL:')
47+
assert versions.contains('BENCHMARK_REPORT:')
48+
assert report.isFile()
49+
assert database.isFile()
50+
assert reportText.contains('Benchmark overview')
51+
assert reportText.contains('15dvxY1LnZYrYe')
52+
assert reportText.contains('g5')
53+
54+
assert snapshot(
55+
workflow.trace.succeeded().size(),
56+
removeFromYamlMap("$outputDir/pipeline_info/collated_software_versions.yml", "Workflow"),
57+
expectedOutputNames
58+
).match()
59+
}
60+
}
61+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"benchmark report consumes external log directory directly": {
3+
"content": [
4+
1,
5+
{
6+
"BENCHMARK_REPORT": {
7+
"duckdb": "1.3.2",
8+
"python": "3.12.13"
9+
}
10+
},
11+
[
12+
"benchmark_report",
13+
"benchmark_report/benchmark.duckdb",
14+
"benchmark_report/benchmark_report.html",
15+
"pipeline_info",
16+
"pipeline_info/collated_software_versions.yml"
17+
]
18+
],
19+
"meta": {
20+
"nf-test": "0.9.2",
21+
"nextflow": "26.03.1"
22+
},
23+
"timestamp": "2026-04-06T21:16:23.609417"
24+
}
25+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# pipeline_benchmark_tarball
2+
3+
## Purpose
4+
Covers benchmark generation when external logs are supplied as tarballs.
5+
6+
## Fixtures
7+
- `workflows/nf_aggregate/assets/test_benchmark.csv`
8+
- tarballs under `workflows/nf_aggregate/assets/logs/`
9+
10+
## Expected behavior
11+
- `EXTRACT_TARBALL` should run for each external input.
12+
- `BENCHMARK_REPORT` should run once after collection.
13+
- Benchmark outputs should include both HTML and DuckDB artifacts.
14+
- The rendered HTML should mention the expected run IDs and groups.
15+
16+
## Edit guidance
17+
If you change tarball extraction, benchmark aggregation, or HTML report content, update this test.
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
def INPUT_PATH = new File('workflows/nf_aggregate/assets/test_benchmark.csv').canonicalPath
2+
3+
def expectedOutputNames = [
4+
'benchmark_report',
5+
'benchmark_report/benchmark.duckdb',
6+
'benchmark_report/benchmark_report.html',
7+
'pipeline_info',
8+
'pipeline_info/collated_software_versions.yml',
9+
]
10+
11+
def collatedVersions = { outdir ->
12+
new File("${outdir}/pipeline_info/collated_software_versions.yml").text
13+
}
14+
15+
nextflow_pipeline {
16+
name "Pipeline benchmark from tarballs"
17+
script "../../main.nf"
18+
tag "pipeline"
19+
tag "nf-aggregate"
20+
tag "benchmark-tarball"
21+
22+
test("benchmark report includes extracted tarball runs") {
23+
tag("benchmark")
24+
25+
when {
26+
params {
27+
input = INPUT_PATH
28+
outdir = "$outputDir"
29+
generate_benchmark_report = true
30+
}
31+
}
32+
33+
then {
34+
def versions = collatedVersions(params.outdir)
35+
def stdout = workflow.stdout.join('\n')
36+
def report = new File("${params.outdir}/benchmark_report/benchmark_report.html")
37+
def database = new File("${params.outdir}/benchmark_report/benchmark.duckdb")
38+
def reportText = report.text
39+
40+
assert workflow.success
41+
assert workflow.trace.succeeded().size() == 3
42+
assert !stdout.contains('Invalid method invocation')
43+
assert stdout.contains('SEQERALABS_NF_AGGREGATE:NF_AGGREGATE:EXTRACT_TARBALL')
44+
assert stdout.contains('SEQERALABS_NF_AGGREGATE:NF_AGGREGATE:BENCHMARK_REPORT')
45+
assert versions.contains('EXTRACT_TARBALL:')
46+
assert versions.contains('BENCHMARK_REPORT:')
47+
assert report.isFile()
48+
assert database.isFile()
49+
assert reportText.contains('Benchmark overview')
50+
assert reportText.contains('Run overview')
51+
assert reportText.contains('Process overview')
52+
assert reportText.contains('Task overview')
53+
assert reportText.contains('15dvxY1LnZYrYe')
54+
assert reportText.contains('5ymDk0hmgqv4L4')
55+
assert reportText.contains('g5')
56+
assert reportText.contains('cpu')
57+
58+
assert snapshot(
59+
workflow.trace.succeeded().size(),
60+
removeFromYamlMap("$outputDir/pipeline_info/collated_software_versions.yml", "Workflow"),
61+
expectedOutputNames
62+
).match()
63+
}
64+
}
65+
}

0 commit comments

Comments
 (0)