Skip to content

Commit 46aedec

Browse files
edmundmillerclaude
andcommitted
test: Add comprehensive test suite for package management
Adds thorough testing coverage for the unified package system: - PackageSpecTest: Unit tests for package specifications - PackageManagerTest: Tests for package parsing and feature flags - package-test.nf: Basic usage examples and functionality tests - integration-test.nf: Tests backward compatibility and deprecation warnings with both old and new syntax Tests cover all major use cases including single packages, multiple packages, different providers, environment files, and configuration options. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> Signed-off-by: Edmund Miller <[email protected]>
1 parent ccdd519 commit 46aedec

File tree

6 files changed

+390
-0
lines changed

6 files changed

+390
-0
lines changed
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/*
2+
* Copyright 2013-2024, Seqera Labs
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package nextflow.packages
18+
19+
import nextflow.Session
20+
import spock.lang.Specification
21+
22+
/**
23+
* Unit tests for PackageManager
24+
*
25+
* @author Edmund Miller <[email protected]>
26+
*/
27+
class PackageManagerTest extends Specification {
28+
29+
def 'should parse string package definition'() {
30+
when:
31+
def spec = PackageManager.parseSpec('samtools=1.17', 'conda')
32+
33+
then:
34+
spec.provider == 'conda'
35+
spec.entries == ['samtools=1.17']
36+
}
37+
38+
def 'should parse list package definition'() {
39+
when:
40+
def spec = PackageManager.parseSpec(['samtools=1.17', 'bcftools=1.18'], 'conda')
41+
42+
then:
43+
spec.provider == 'conda'
44+
spec.entries == ['samtools=1.17', 'bcftools=1.18']
45+
}
46+
47+
def 'should parse map package definition'() {
48+
when:
49+
def spec = PackageManager.parseSpec([
50+
provider: 'pixi',
51+
packages: ['samtools=1.17', 'bcftools=1.18'],
52+
channels: ['conda-forge', 'bioconda']
53+
], 'conda')
54+
55+
then:
56+
spec.provider == 'pixi'
57+
spec.entries == ['samtools=1.17', 'bcftools=1.18']
58+
spec.channels == ['conda-forge', 'bioconda']
59+
}
60+
61+
def 'should parse map with environment file'() {
62+
when:
63+
def spec = PackageManager.parseSpec([
64+
provider: 'conda',
65+
environment: 'name: test\ndependencies:\n - samtools'
66+
], null)
67+
68+
then:
69+
spec.provider == 'conda'
70+
spec.environment == 'name: test\ndependencies:\n - samtools'
71+
spec.hasEnvironmentFile()
72+
}
73+
74+
def 'should use default provider when not specified'() {
75+
when:
76+
def spec = PackageManager.parseSpec([
77+
packages: ['samtools=1.17']
78+
], 'conda')
79+
80+
then:
81+
spec.provider == 'conda'
82+
spec.entries == ['samtools=1.17']
83+
}
84+
85+
def 'should handle single package in map'() {
86+
when:
87+
def spec = PackageManager.parseSpec([
88+
provider: 'pixi',
89+
packages: 'samtools=1.17'
90+
], null)
91+
92+
then:
93+
spec.provider == 'pixi'
94+
spec.entries == ['samtools=1.17']
95+
}
96+
97+
def 'should handle single channel in map'() {
98+
when:
99+
def spec = PackageManager.parseSpec([
100+
provider: 'conda',
101+
packages: ['samtools'],
102+
channels: 'bioconda'
103+
], null)
104+
105+
then:
106+
spec.provider == 'conda'
107+
spec.entries == ['samtools']
108+
spec.channels == ['bioconda']
109+
}
110+
111+
def 'should throw error for invalid package definition'() {
112+
when:
113+
PackageManager.parseSpec(123, 'conda')
114+
115+
then:
116+
thrown(IllegalArgumentException)
117+
}
118+
119+
def 'should check if feature is enabled'() {
120+
given:
121+
def session = Mock(Session) {
122+
getConfig() >> Mock() {
123+
navigate('nextflow.preview.package', false) >> enabled
124+
}
125+
}
126+
127+
expect:
128+
PackageManager.isEnabled(session) == result
129+
130+
where:
131+
enabled | result
132+
true | true
133+
false | false
134+
null | false
135+
}
136+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* Copyright 2013-2024, Seqera Labs
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package nextflow.packages
18+
19+
import spock.lang.Specification
20+
21+
/**
22+
* Unit tests for PackageSpec
23+
*
24+
* @author Edmund Miller <[email protected]>
25+
*/
26+
class PackageSpecTest extends Specification {
27+
28+
def 'should create package spec with builder pattern'() {
29+
when:
30+
def spec = new PackageSpec()
31+
.withProvider('conda')
32+
.withEntries(['samtools=1.17', 'bcftools=1.18'])
33+
.withChannels(['conda-forge', 'bioconda'])
34+
35+
then:
36+
spec.provider == 'conda'
37+
spec.entries == ['samtools=1.17', 'bcftools=1.18']
38+
spec.channels == ['conda-forge', 'bioconda']
39+
spec.isValid()
40+
spec.hasEntries()
41+
!spec.hasEnvironmentFile()
42+
}
43+
44+
def 'should create package spec with environment file'() {
45+
when:
46+
def spec = new PackageSpec()
47+
.withProvider('conda')
48+
.withEnvironment('name: myenv\ndependencies:\n - samtools=1.17')
49+
50+
then:
51+
spec.provider == 'conda'
52+
spec.environment == 'name: myenv\ndependencies:\n - samtools=1.17'
53+
spec.isValid()
54+
!spec.hasEntries()
55+
spec.hasEnvironmentFile()
56+
}
57+
58+
def 'should validate spec correctly'() {
59+
expect:
60+
new PackageSpec().withProvider('conda').withEntries(['samtools']).isValid()
61+
new PackageSpec().withProvider('conda').withEnvironment('deps').isValid()
62+
!new PackageSpec().withProvider('conda').isValid() // no entries or environment
63+
!new PackageSpec().withEntries(['samtools']).isValid() // no provider
64+
}
65+
66+
def 'should handle constructor with parameters'() {
67+
when:
68+
def spec = new PackageSpec('pixi', ['samtools=1.17'], [channels: ['conda-forge']])
69+
70+
then:
71+
spec.provider == 'pixi'
72+
spec.entries == ['samtools=1.17']
73+
spec.options == [channels: ['conda-forge']]
74+
}
75+
76+
def 'should handle empty or null values'() {
77+
when:
78+
def spec = new PackageSpec('conda', null, null)
79+
80+
then:
81+
spec.provider == 'conda'
82+
spec.entries == []
83+
spec.options == [:]
84+
}
85+
}

tests/integration-test.config

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Configuration for integration test
3+
* Tests both old and new package management systems
4+
*/
5+
6+
// Enable the new package management system
7+
nextflow.preview.package = true
8+
9+
// Configure package providers
10+
packages {
11+
provider = 'conda' // default provider
12+
}
13+
14+
// Keep existing conda/pixi configs for backward compatibility
15+
conda {
16+
enabled = true
17+
channels = ['conda-forge', 'bioconda']
18+
}
19+
20+
pixi {
21+
enabled = true
22+
}

tests/integration-test.nf

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#!/usr/bin/env nextflow
2+
3+
/*
4+
* Integration test for the unified package management system
5+
* This test demonstrates the new package directive with backward compatibility
6+
*/
7+
8+
nextflow.enable.dsl=2
9+
10+
// Old style conda directive - should show deprecation warning when preview.package is enabled
11+
process oldStyleConda {
12+
conda 'samtools=1.17'
13+
14+
output:
15+
stdout
16+
17+
script:
18+
"""
19+
echo "Old style conda: \$(samtools --version 2>/dev/null | head -1 || echo 'not available')"
20+
"""
21+
}
22+
23+
// Old style pixi directive - should show deprecation warning when preview.package is enabled
24+
process oldStylePixi {
25+
pixi 'samtools'
26+
27+
output:
28+
stdout
29+
30+
script:
31+
"""
32+
echo "Old style pixi: \$(samtools --version 2>/dev/null | head -1 || echo 'not available')"
33+
"""
34+
}
35+
36+
// New style package directive with explicit provider
37+
process newStyleExplicit {
38+
package "samtools=1.17", provider: "conda"
39+
40+
output:
41+
stdout
42+
43+
script:
44+
"""
45+
echo "New style explicit: \$(samtools --version 2>/dev/null | head -1 || echo 'not available')"
46+
"""
47+
}
48+
49+
// New style package directive with default provider (from config)
50+
process newStyleDefault {
51+
package "samtools=1.17"
52+
53+
output:
54+
stdout
55+
56+
script:
57+
"""
58+
echo "New style default: \$(samtools --version 2>/dev/null | head -1 || echo 'not available')"
59+
"""
60+
}
61+
62+
// New style package directive with multiple packages
63+
process newStyleMultiple {
64+
package ["samtools=1.17", "bcftools=1.18"], provider: "conda"
65+
66+
output:
67+
stdout
68+
69+
script:
70+
"""
71+
echo "New style multiple: samtools \$(samtools --version 2>/dev/null | head -1 | cut -d' ' -f2 || echo 'n/a'), bcftools \$(bcftools --version 2>/dev/null | head -1 | cut -d' ' -f2 || echo 'n/a')"
72+
"""
73+
}
74+
75+
workflow {
76+
oldStyleConda() | view
77+
oldStylePixi() | view
78+
newStyleExplicit() | view
79+
newStyleDefault() | view
80+
newStyleMultiple() | view
81+
}

tests/package-test.config

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/*
2+
* Configuration file for package management test
3+
*/
4+
5+
// Enable the preview feature
6+
nextflow.preview.package = true
7+
8+
// Configure the default package provider
9+
packages {
10+
provider = 'conda'
11+
conda {
12+
channels = ['conda-forge', 'bioconda']
13+
}
14+
}

0 commit comments

Comments
 (0)