diff --git a/docs/docs/testcases/setup.md b/docs/docs/testcases/setup.md new file mode 100644 index 00000000..d58d070c --- /dev/null +++ b/docs/docs/testcases/setup.md @@ -0,0 +1,155 @@ +# Setup Method + +The setup method allows you to specify processes or workflows that need to be executed before the primary `when` block. It serves as a mechanism to prepare the required input data or set up essential steps prior to the primary processing block. + +## Syntax + +The setup method is typically used within the context of a test case. The basic syntax for the setup method is as follows: + +```groovy +test("my test"){ + setup { + // Define and execute dependent processes or workflows here + } +} +``` + +Within the setup block, you can use the `run` method to define and execute dependent processes or workflows. + +The `run` method syntax for a process is as follows: + +```groovy +run("ProcessName") { + script "path/to/process/script.nf" + process { + // Define the process inputs here + } +} +``` + +The `run` method syntax for a workflow is as follows: + +```groovy +run("WorkflowName") { + script "path/to/workflow/script.nf" + workflow { + // Define the workflow inputs here + } +} +``` + +!!! warning + + Please keep in mind that changes in procsses or workflows, which are executed in the setup method, can result in a failed test run. + +## Example Usage + +### 1. Local Setup Method + +In this example, we create a setup method within a Nextflow process definition to execute a dependent process named "ABRICATE_RUN." This process generates input data that is required for the primary process "ABRICATE_SUMMARY." The `setup` block specifies the execution of "ABRICATE_RUN," and the `when` block defines the processing logic for "ABRICATE_SUMMARY." + +```groovy +nextflow_process { + + name "Test process data" + + script "../main.nf" + process "ABRICATE_SUMMARY" + config "./nextflow.config" + + test("Should use process ABRICATE_RUN to generate input data") { + + setup { + + run("ABRICATE_RUN") { + script "../../run/main.nf" + process { + """ + input[0] = Channel.fromList([ + tuple([ id:'test1', single_end:false ], // meta map + file(params.test_data['bacteroides_fragilis']['genome']['genome_fna_gz'], checkIfExists: true)), + tuple([ id:'test2', single_end:false ], + file(params.test_data['haemophilus_influenzae']['genome']['genome_fna_gz'], checkIfExists: true)) + ]) + """ + } + } + + } + + when { + process { + """ + input[0] = ABRICATE_RUN.out.report.collect{ meta, report -> report }.map{ report -> [[ id: 'test_summary'], report]} + """ + } + } + + then { + assert process.success + assert snapshot(process.out).match() + } + } + +} +``` + +### 2. Global Setup Method + +In this example, a global setup method is defined for all tests within a Nextflow process definition. The setup method is applied to multiple test cases, ensuring consistent setup for each test. This approach is useful when multiple tests share the same setup requirements. + +```groovy +nextflow_process { + + name "Test process data" + + script "../main.nf" + process "ABRICATE_SUMMARY" + config "./nextflow.config" + + setup { + run("ABRICATE_RUN") { + script "../../run/main.nf" + process { + """ + input[0] = Channel.fromList([ + tuple([ id:'test1', single_end:false ], // meta map + file(params.test_data['bacteroides_fragilis']['genome']['genome_fna_gz'], checkIfExists: true)), + tuple([ id:'test2', single_end:false ], + file(params.test_data['haemophilus_influenzae']['genome']['genome_fna_gz'], checkIfExists: true)) + ]) + """ + } + } + } + + test("first test") { + when { + process { + """ + input[0] = ABRICATE_RUN.out.report.collect{ meta, report -> report }.map{ report -> [[ id: 'test_summary'], report]} + """ + } + } + then { + assert process.success + assert snapshot(process.out).match() + } + } + + test("second test") { + when { + process { + """ + input[0] = ABRICATE_RUN.out.report.collect{ meta, report -> report }.map{ report -> [[ id: 'test_summary'], report]} + """ + } + } + then { + assert process.success + assert snapshot(process.out).match() + } + } + +} +``` diff --git a/mkdocs.yml b/mkdocs.yml index 050bc895..db5bcc77 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -4,16 +4,16 @@ copyright: "© 2021 - 2023 Lukas Forer and Sebastian Schönherr" theme: name: material features: - - content.tooltips - #- navigation.expand - - navigation.footer - - navigation.tabs - #- navigation.tabs.sticky - - search.highlight - - search.share - - search.suggest - - toc.integrate - - content.tabs.link + - content.tooltips + #- navigation.expand + - navigation.footer + - navigation.tabs + #- navigation.tabs.sticky + - search.highlight + - search.share + - search.suggest + - toc.integrate + - content.tabs.link font: text: Segoe UI @@ -36,44 +36,44 @@ nav: - Home: index.md - Installation: installation.md - Documentation: - - Getting Started: docs/getting-started.md - - Writing Tests: - - Pipeline Testing: docs/testcases/nextflow_pipeline.md - - Workflow Testing: docs/testcases/nextflow_workflow.md - - Process Testing: docs/testcases/nextflow_process.md - - Function Testing: docs/testcases/nextflow_function.md - - Params Dictionary: docs/testcases/params.md - - Global Variables: docs/testcases/global_variables.md - - Running Tests: docs/running-tests.md - - Writing Assertions: - - Power Assertions: docs/assertions/assertions.md - - Files: docs/assertions/files.md - - Snapshots: docs/assertions/snapshots.md - - Regular Expressions: docs/assertions/regular-expressions.md - - FASTA Files: docs/assertions/fasta.md - - Using Third-Party Libraries: docs/assertions/libraries.md - - Command Line Interface (CLI): - - init: docs/cli/init.md - - generate: docs/cli/generate.md - - test: docs/cli/test.md - - list: docs/cli/list.md - - clean: docs/cli/clean.md - - Configuration: docs/configuration.md - - Plugins: - - Available Plugins: https://code.askimed.com/nf-test-plugins - - Using Plugins: docs/plugins/using-plugins.md - - Developing Plugins: docs/plugins/developing-plugins.md + - Getting Started: docs/getting-started.md + - Writing Tests: + - Pipeline Testing: docs/testcases/nextflow_pipeline.md + - Workflow Testing: docs/testcases/nextflow_workflow.md + - Process Testing: docs/testcases/nextflow_process.md + - Function Testing: docs/testcases/nextflow_function.md + - Params Dictionary: docs/testcases/params.md + - Setup Method: docs/testcases/setup.md + - Global Variables: docs/testcases/global_variables.md + - Running Tests: docs/running-tests.md + - Writing Assertions: + - Power Assertions: docs/assertions/assertions.md + - Files: docs/assertions/files.md + - Snapshots: docs/assertions/snapshots.md + - Regular Expressions: docs/assertions/regular-expressions.md + - FASTA Files: docs/assertions/fasta.md + - Using Third-Party Libraries: docs/assertions/libraries.md + - Command Line Interface (CLI): + - init: docs/cli/init.md + - generate: docs/cli/generate.md + - test: docs/cli/test.md + - list: docs/cli/list.md + - clean: docs/cli/clean.md + - Configuration: docs/configuration.md + - Plugins: + - Available Plugins: https://code.askimed.com/nf-test-plugins + - Using Plugins: docs/plugins/using-plugins.md + - Developing Plugins: docs/plugins/developing-plugins.md - Resources: resources.md - About: about.md - markdown_extensions: - admonition - pymdownx.details - pymdownx.superfences - pymdownx.tabbed: - alternate_style: true + alternate_style: true - attr_list - pymdownx.emoji: emoji_index: !!python/name:materialx.emoji.twemoji - emoji_generator: !!python/name:materialx.emoji.to_svg \ No newline at end of file + emoji_generator: !!python/name:materialx.emoji.to_svg diff --git a/src/main/java/com/askimed/nf/test/core/AbstractTest.java b/src/main/java/com/askimed/nf/test/core/AbstractTest.java index 3cc6e71d..eb2ff643 100644 --- a/src/main/java/com/askimed/nf/test/core/AbstractTest.java +++ b/src/main/java/com/askimed/nf/test/core/AbstractTest.java @@ -84,7 +84,14 @@ public AbstractTest(AbstractTestSuite parent) { } public void config(String config) { - this.config = new File(config); + if (config == null) { + return; + } + if (parent.isRelative(config)) { + this.config = new File(parent.makeAbsolute(config)); + } else { + this.config = new File(config); + } } public File getConfig() { diff --git a/src/main/java/com/askimed/nf/test/core/AbstractTestSuite.java b/src/main/java/com/askimed/nf/test/core/AbstractTestSuite.java index 3b7c7af2..5a729882 100644 --- a/src/main/java/com/askimed/nf/test/core/AbstractTestSuite.java +++ b/src/main/java/com/askimed/nf/test/core/AbstractTestSuite.java @@ -20,7 +20,7 @@ public abstract class AbstractTestSuite implements ITestSuite { private File globalConfig = null; - private File localConfig = null; + private String localConfig = null; private List tests = new Vector(); @@ -62,7 +62,7 @@ public void script(String script) { } public String getScript() { - if (script != null && isRelative(script)) { + if (isRelative(script)) { return makeAbsolute(script); } else { return script; @@ -105,7 +105,7 @@ public void profile(String profile) { } public void config(String config) { - this.localConfig = new File(config); + this.localConfig = config; } public void setName(String name) { @@ -159,12 +159,15 @@ public File getGlobalConfigFile() { return globalConfig; } - public void setLocalConfig(File localConfig) { - this.localConfig = localConfig; - } - public File getLocalConfig() { - return localConfig; + if (localConfig == null) { + return null; + } + if (isRelative(localConfig)) { + return new File(makeAbsolute(localConfig)); + } else { + return new File(localConfig); + } } public File getHomeDirectory() { @@ -243,11 +246,14 @@ public boolean hasFailedTests() { return failedTests; } - protected String makeAbsolute(String path) { + public String makeAbsolute(String path) { return new File(directory, path).getAbsolutePath(); } - protected boolean isRelative(String path) { + public boolean isRelative(String path) { + if (path == null) { + return false; + } return path.startsWith("../") || path.startsWith("./"); } diff --git a/src/main/java/com/askimed/nf/test/lang/Dependency.java b/src/main/java/com/askimed/nf/test/lang/Dependency.java new file mode 100644 index 00000000..1a274e4a --- /dev/null +++ b/src/main/java/com/askimed/nf/test/lang/Dependency.java @@ -0,0 +1,65 @@ +package com.askimed.nf.test.lang; + +import groovy.lang.Closure; + +public class Dependency { + + private String script; + + private String name; + + private String mapping; + + public Dependency(String name, Closure closure) { + this.name = name; + closure.setDelegate(this); + closure.setResolveStrategy(Closure.DELEGATE_FIRST); + closure.call(); + } + + public void script(String script) { + this.script = script; + } + + public String getScript() { + return script; + } + + public void setScript(String script) { + this.script = script; + } + + public void process(Closure closure) { + closure.setDelegate(this); + closure.setResolveStrategy(Closure.DELEGATE_FIRST); + Object mapping = closure.call(); + if (mapping != null) { + this.mapping = mapping.toString(); + } + } + + public void workflow(Closure closure) { + process(closure); + } + + public void function(Closure closure) { + process(closure); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getMapping() { + return mapping; + } + + public void setMapping(String mapping) { + this.mapping = mapping; + } + +} diff --git a/src/main/java/com/askimed/nf/test/lang/process/ProcessContext.java b/src/main/java/com/askimed/nf/test/lang/process/ProcessContext.java index 692076a5..8f22ce90 100644 --- a/src/main/java/com/askimed/nf/test/lang/process/ProcessContext.java +++ b/src/main/java/com/askimed/nf/test/lang/process/ProcessContext.java @@ -1,6 +1,10 @@ package com.askimed.nf.test.lang.process; +import java.util.List; +import java.util.Vector; + import com.askimed.nf.test.core.ITest; +import com.askimed.nf.test.lang.Dependency; import com.askimed.nf.test.lang.TestContext; import groovy.lang.Closure; @@ -11,6 +15,8 @@ public class ProcessContext extends TestContext { private Closure processClosure; + private List dependencies = new Vector(); + public ProcessContext(ITest test) { super(test); } @@ -43,5 +49,14 @@ public void evaluateProcessClosure() { } } - + + public void run(String process, Closure closure) { + Dependency dependency = new Dependency(process, closure); + dependencies.add(dependency); + } + + public List getDependencies() { + return dependencies; + } + } diff --git a/src/main/java/com/askimed/nf/test/lang/process/ProcessTest.java b/src/main/java/com/askimed/nf/test/lang/process/ProcessTest.java index 63781e39..42d3fdde 100644 --- a/src/main/java/com/askimed/nf/test/lang/process/ProcessTest.java +++ b/src/main/java/com/askimed/nf/test/lang/process/ProcessTest.java @@ -9,6 +9,7 @@ import org.codehaus.groovy.control.CompilationFailedException; import com.askimed.nf.test.core.AbstractTest; +import com.askimed.nf.test.lang.Dependency; import com.askimed.nf.test.lang.TestCode; import com.askimed.nf.test.nextflow.NextflowCommand; import com.askimed.nf.test.util.AnsiText; @@ -82,7 +83,7 @@ public void autoSort(boolean autoSort) { public void execute() throws Throwable { super.execute(); - + File script = new File(parent.getScript()); if (!script.exists()) { @@ -91,6 +92,10 @@ public void execute() throws Throwable { context.init(this); + if (parent.getSetup() != null) { + parent.getSetup().execute(context); + } + if (setup != null) { setup.execute(context); } @@ -126,8 +131,8 @@ public void execute() throws Throwable { } File projectConfig = new File("nextflow.config"); if (projectConfig.exists()) { - nextflow.addConfig(projectConfig); - } + nextflow.addConfig(projectConfig); + } nextflow.addConfig(parent.getGlobalConfigFile()); nextflow.addConfig(parent.getLocalConfig()); nextflow.addConfig(getConfig()); @@ -179,9 +184,26 @@ protected void writeWorkflowMock(File file) throws IOException, CompilationFaile script = new File(script).getAbsolutePath(); } + // update dependency paths + for (Dependency dependency : context.getDependencies()) { + String _script = dependency.getScript(); + if (_script == null) { + dependency.setScript(script); + } else { + if (parent.isRelative(_script)) { + _script = parent.makeAbsolute(_script); + } + if (!_script.startsWith("/") && !_script.startsWith("./")) { + _script = new File(_script).getAbsolutePath(); + } + dependency.setScript(_script); + } + } + Map binding = new HashMap(); binding.put("process", parent.getProcess()); binding.put("script", script); + binding.put("dependencies", context.getDependencies()); // Get body of when closure binding.put("mapping", context.getProcess().getMapping()); diff --git a/src/main/java/com/askimed/nf/test/lang/process/ProcessTestSuite.java b/src/main/java/com/askimed/nf/test/lang/process/ProcessTestSuite.java index 8f00b80c..8fc15104 100644 --- a/src/main/java/com/askimed/nf/test/lang/process/ProcessTestSuite.java +++ b/src/main/java/com/askimed/nf/test/lang/process/ProcessTestSuite.java @@ -4,13 +4,17 @@ import com.askimed.nf.test.core.AbstractTestSuite; import com.askimed.nf.test.core.ITest; +import com.askimed.nf.test.lang.TestCode; import groovy.lang.Closure; +import groovy.lang.DelegatesTo; public class ProcessTestSuite extends AbstractTestSuite { private String process; + private TestCode setup; + public void process(String process) { this.process = process; } @@ -27,6 +31,14 @@ public void test(String name, Closure closure) throws IOException { addTestClosure(name, closure); } + public void setup(@DelegatesTo(value = ProcessTest.class, strategy = Closure.DELEGATE_ONLY) final Closure closure) { + setup = new TestCode(closure); + } + + public TestCode getSetup() { + return setup; + } + @Override protected ITest getNewTestInstance(String name) { ProcessTest test = new ProcessTest(this); diff --git a/src/main/java/com/askimed/nf/test/lang/workflow/WorkflowContext.java b/src/main/java/com/askimed/nf/test/lang/workflow/WorkflowContext.java index 47ed8484..a9ae6efc 100644 --- a/src/main/java/com/askimed/nf/test/lang/workflow/WorkflowContext.java +++ b/src/main/java/com/askimed/nf/test/lang/workflow/WorkflowContext.java @@ -1,6 +1,10 @@ package com.askimed.nf.test.lang.workflow; +import java.util.List; +import java.util.Vector; + import com.askimed.nf.test.core.ITest; +import com.askimed.nf.test.lang.Dependency; import com.askimed.nf.test.lang.TestContext; import groovy.lang.Closure; @@ -11,10 +15,12 @@ public class WorkflowContext extends TestContext { private Workflow workflow = new Workflow(); + private List dependencies = new Vector(); + public WorkflowContext(ITest test) { super(test); } - + public void workflow(Closure closure) { workflowClosure = closure; } @@ -40,4 +46,13 @@ public void setWorkflow(Workflow workflow) { this.workflow = workflow; } + public void run(String process, Closure closure) { + Dependency dependency = new Dependency(process, closure); + dependencies.add(dependency); + } + + public List getDependencies() { + return dependencies; + } + } diff --git a/src/main/java/com/askimed/nf/test/lang/workflow/WorkflowTest.java b/src/main/java/com/askimed/nf/test/lang/workflow/WorkflowTest.java index cd451230..c595990d 100644 --- a/src/main/java/com/askimed/nf/test/lang/workflow/WorkflowTest.java +++ b/src/main/java/com/askimed/nf/test/lang/workflow/WorkflowTest.java @@ -9,6 +9,7 @@ import org.codehaus.groovy.control.CompilationFailedException; import com.askimed.nf.test.core.AbstractTest; +import com.askimed.nf.test.lang.Dependency; import com.askimed.nf.test.lang.TestCode; import com.askimed.nf.test.lang.pipeline.PipelineTest; import com.askimed.nf.test.nextflow.NextflowCommand; @@ -104,6 +105,10 @@ public void execute() throws Throwable { context.init(this); + if (parent.getSetup() != null) { + parent.getSetup().execute(context); + } + if (setup != null) { setup.execute(context); } @@ -186,11 +191,28 @@ protected void writeWorkflowMock(File file) throws IOException, CompilationFaile script = new File(script).getAbsolutePath(); } + // update dependency paths + for (Dependency dependency : context.getDependencies()) { + String _script = dependency.getScript(); + if (_script == null) { + dependency.setScript(script); + } else { + if (parent.isRelative(_script)) { + _script = parent.makeAbsolute(_script); + } + if (!_script.startsWith("/") && !_script.startsWith("./")) { + _script = new File(_script).getAbsolutePath(); + } + dependency.setScript(_script); + } + } + String name = workflow != null ? workflow : parent.getWorkflow(); Map binding = new HashMap(); binding.put("workflow", name); binding.put("script", script); + binding.put("dependencies", context.getDependencies()); // Get body of when closure binding.put("mapping", context.getWorkflow().getMapping()); diff --git a/src/main/java/com/askimed/nf/test/lang/workflow/WorkflowTestSuite.java b/src/main/java/com/askimed/nf/test/lang/workflow/WorkflowTestSuite.java index 701dbbe8..39ab5a10 100644 --- a/src/main/java/com/askimed/nf/test/lang/workflow/WorkflowTestSuite.java +++ b/src/main/java/com/askimed/nf/test/lang/workflow/WorkflowTestSuite.java @@ -4,13 +4,18 @@ import com.askimed.nf.test.core.AbstractTestSuite; import com.askimed.nf.test.core.ITest; +import com.askimed.nf.test.lang.TestCode; +import com.askimed.nf.test.lang.process.ProcessTest; import groovy.lang.Closure; +import groovy.lang.DelegatesTo; public class WorkflowTestSuite extends AbstractTestSuite { private String workflow; + private TestCode setup; + public void workflow(String workflow) { this.workflow = workflow; } @@ -27,6 +32,14 @@ public void test(String name, Closure closure) throws IOException { addTestClosure(name, closure); } + public void setup(@DelegatesTo(value = ProcessTest.class, strategy = Closure.DELEGATE_ONLY) final Closure closure) { + setup = new TestCode(closure); + } + + public TestCode getSetup() { + return setup; + } + @Override protected ITest getNewTestInstance(String name) { WorkflowTest test = new WorkflowTest(this); @@ -34,5 +47,4 @@ protected ITest getNewTestInstance(String name) { return test; } - } \ No newline at end of file diff --git a/src/main/java/com/askimed/nf/test/util/Command.java b/src/main/java/com/askimed/nf/test/util/Command.java index cd0cb330..47d0e2d3 100644 --- a/src/main/java/com/askimed/nf/test/util/Command.java +++ b/src/main/java/com/askimed/nf/test/util/Command.java @@ -14,8 +14,6 @@ public class Command { private String directory = null; - private StringBuffer stdout = new StringBuffer(); - private String stdoutFileName = null; private String stderrFileName = null; @@ -63,6 +61,8 @@ public int execute() { try { ProcessBuilder builder = new ProcessBuilder(command); + // ensure it works on MacOS + builder.environment().put("PATH", builder.environment().get("PATH") + ":" + "/usr/local/bin/"); if (directory != null) { builder.directory(new File(directory)); } @@ -127,10 +127,6 @@ public String toString() { return result; } - public String getStdOut() { - return stdout.toString(); - } - public String getName() { return cmd; } diff --git a/src/main/resources/com/askimed/nf/test/lang/process/WorkflowMock.nf b/src/main/resources/com/askimed/nf/test/lang/process/WorkflowMock.nf index 6245975d..d1d77b51 100644 --- a/src/main/resources/com/askimed/nf/test/lang/process/WorkflowMock.nf +++ b/src/main/resources/com/askimed/nf/test/lang/process/WorkflowMock.nf @@ -6,10 +6,10 @@ nextflow.enable.dsl=2 // comes from nf-test to store json files params.nf_test_output = "" -// process mapping -def input = [] -${mapping} -//---- +// include dependencies +<% for (dependency in dependencies) { %> +include { ${dependency.name} } from '${dependency.script}' +<% } %> // include test process include { ${process} } from '${script}' @@ -24,6 +24,20 @@ def jsonOutput = workflow { + // run dependencies + <% for (dependency in dependencies) { %> + { + def input = [] + ${dependency.mapping} + ${dependency.name}(*input) + } + <% } %> + + // process mapping + def input = [] + ${mapping} + //---- + //run process ${process}(*input) diff --git a/src/main/resources/com/askimed/nf/test/lang/workflow/WorkflowMock.nf b/src/main/resources/com/askimed/nf/test/lang/workflow/WorkflowMock.nf index ae87caa3..268bec33 100644 --- a/src/main/resources/com/askimed/nf/test/lang/workflow/WorkflowMock.nf +++ b/src/main/resources/com/askimed/nf/test/lang/workflow/WorkflowMock.nf @@ -6,12 +6,12 @@ nextflow.enable.dsl=2 // comes from nf-test to store json files params.nf_test_output = "" -// process mapping -def input = [] -${mapping} -//---- +// include dependencies +<% for (dependency in dependencies) { %> +include { ${dependency.name} } from '${dependency.script}' +<% } %> -// include test process +// include test workflow include { ${workflow} } from '${script}' // define custom rules for JSON that will be generated. @@ -24,6 +24,20 @@ def jsonOutput = workflow { + // run dependencies + <% for (dependency in dependencies) { %> + { + def input = [] + ${dependency.mapping} + ${dependency.name}(*input) + } + <% } %> + + // workflow mapping + def input = [] + ${mapping} + //---- + //run workflow ${workflow}(*input) diff --git a/src/test/java/com/askimed/nf/test/lang/ProcessTest.java b/src/test/java/com/askimed/nf/test/lang/ProcessTest.java index b4683079..c8580020 100644 --- a/src/test/java/com/askimed/nf/test/lang/ProcessTest.java +++ b/src/test/java/com/askimed/nf/test/lang/ProcessTest.java @@ -216,7 +216,24 @@ public void testScriptWithRelativePathInSubfolder() throws Exception { assertEquals(0, exitCode); } + + @Test + public void testDependencies() throws Exception { + + App app = new App(); + int exitCode = app.run(new String[] { "test", "test-data/process/dependencies/process_data.nf.test" }); + + } + + @Test + public void testDependenciesAbricate() throws Exception { + + App app = new App(); + int exitCode = app.run(new String[] { "test", "test-data/process/abricate/summary/tests/main.nf.test" }); + assertEquals(0, exitCode); + } + @Test public void testProfiles() throws Exception { @@ -244,7 +261,7 @@ public void testProfilesOverwrite() throws Exception { assertEquals(0, exitCode); } - + @Test public void testProfilesOverwriteInConfig() throws Exception { diff --git a/test-data/process/abricate/run/main.nf b/test-data/process/abricate/run/main.nf new file mode 100644 index 00000000..87ab0df9 --- /dev/null +++ b/test-data/process/abricate/run/main.nf @@ -0,0 +1,34 @@ +process ABRICATE_RUN { + tag "$meta.id" + label 'process_medium' + + conda "bioconda::abricate=1.0.1" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/abricate%3A1.0.1--ha8f3691_1': + 'biocontainers/abricate:1.0.1--ha8f3691_1' }" + + input: + tuple val(meta), path(assembly) + + output: + tuple val(meta), path("*.txt"), emit: report + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + """ + abricate \\ + $assembly \\ + $args \\ + --threads $task.cpus > ${prefix}.txt + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + abricate: \$(echo \$(abricate --version 2>&1) | sed 's/^.*abricate //' ) + END_VERSIONS + """ +} diff --git a/test-data/process/abricate/summary/main.nf b/test-data/process/abricate/summary/main.nf new file mode 100644 index 00000000..97759f47 --- /dev/null +++ b/test-data/process/abricate/summary/main.nf @@ -0,0 +1,33 @@ +process ABRICATE_SUMMARY { + tag "$meta.id" + label 'process_single' + + conda "bioconda::abricate=1.0.1" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/abricate%3A1.0.1--ha8f3691_1': + 'biocontainers/abricate:1.0.1--ha8f3691_1' }" + + input: + tuple val(meta), path(reports) + + output: + tuple val(meta), path("*.txt"), emit: report + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + """ + abricate \\ + --summary \\ + $reports > ${prefix}.txt + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + abricate: \$(echo \$(abricate --version 2>&1) | sed 's/^.*abricate //' ) + END_VERSIONS + """ +} diff --git a/test-data/process/abricate/summary/tests/main.nf.test b/test-data/process/abricate/summary/tests/main.nf.test new file mode 100644 index 00000000..993fc056 --- /dev/null +++ b/test-data/process/abricate/summary/tests/main.nf.test @@ -0,0 +1,45 @@ +nextflow_process { + + name "Test process data" + + script "../main.nf" + process "ABRICATE_SUMMARY" + config "./nextflow.config" + + test("Should use process ABRICATE_RUN to generate input data") { + + setup { + + run("ABRICATE_RUN") { + script "../../run/main.nf" + process { + """ + input[0] = Channel.fromList([ + tuple([ id:'test1', single_end:false ], // meta map + file(params.test_data['bacteroides_fragilis']['genome']['genome_fna_gz'], checkIfExists: true)), + tuple([ id:'test2', single_end:false ], + file(params.test_data['haemophilus_influenzae']['genome']['genome_fna_gz'], checkIfExists: true)) + ]) + """ + } + } + + } + + + + when { + process { + """ + input[0] = ABRICATE_RUN.out.report.collect{ meta, report -> report }.map{ report -> [[ id: 'test_summary'], report]} + """ + } + } + + then { + assert process.success + assert snapshot(process.out).match() + } + } + +} diff --git a/test-data/process/abricate/summary/tests/main.nf.test.snap b/test-data/process/abricate/summary/tests/main.nf.test.snap new file mode 100644 index 00000000..916db3b8 --- /dev/null +++ b/test-data/process/abricate/summary/tests/main.nf.test.snap @@ -0,0 +1,31 @@ +{ + "Should use process ABRICATE_RUN to generate input data": { + "content": [ + { + "0": [ + [ + { + "id": "test_summary" + }, + "test_summary.txt:md5,a4ec7010e75404ce3a1033f0c4b4a7f9" + ] + ], + "1": [ + "versions.yml:md5,1fadc3c51127e35186a8f1d4ec21ea07" + ], + "report": [ + [ + { + "id": "test_summary" + }, + "test_summary.txt:md5,a4ec7010e75404ce3a1033f0c4b4a7f9" + ] + ], + "versions": [ + "versions.yml:md5,1fadc3c51127e35186a8f1d4ec21ea07" + ] + } + ], + "timestamp": "2023-10-05T13:55:50.988633" + } +} \ No newline at end of file diff --git a/test-data/process/abricate/summary/tests/nextflow.config b/test-data/process/abricate/summary/tests/nextflow.config new file mode 100644 index 00000000..a80fa6a1 --- /dev/null +++ b/test-data/process/abricate/summary/tests/nextflow.config @@ -0,0 +1,4 @@ +includeConfig 'https://raw.githubusercontent.com/nf-core/modules/master/tests/config/test_data.config' + +docker.enabled = true +docker.registry = 'quay.io' diff --git a/test-data/process/dependencies/generate_data.nf b/test-data/process/dependencies/generate_data.nf new file mode 100644 index 00000000..ee70f442 --- /dev/null +++ b/test-data/process/dependencies/generate_data.nf @@ -0,0 +1,13 @@ +process GENERATE_DATA { + + input: + val name + + output: + path "*.txt", emit: results + + """ + echo "hello ${name}!" > "data.txt" + """ + +} diff --git a/test-data/process/dependencies/process_data.nf b/test-data/process/dependencies/process_data.nf new file mode 100644 index 00000000..1f619176 --- /dev/null +++ b/test-data/process/dependencies/process_data.nf @@ -0,0 +1,17 @@ +process PROCESS_DATA { + + publishDir "${params.outdir}", mode: 'copy' + + input: + val name + path input + + output: + path "output.txt", emit: results + + """ + cp ${input} output.txt + echo "hey ${name}!" >> "output.txt" + """ + +} diff --git a/test-data/process/dependencies/process_data.nf.test b/test-data/process/dependencies/process_data.nf.test new file mode 100644 index 00000000..7b28bfca --- /dev/null +++ b/test-data/process/dependencies/process_data.nf.test @@ -0,0 +1,36 @@ +nextflow_process { + + name "Test process data" + + script "./process_data.nf" + process "PROCESS_DATA" + + test("Should use process GENERATE_DATA to generate input data") { + + setup { + run("GENERATE_DATA") { + script "./generate_data.nf" + process { + """ + input[0] = "nf-core" + """ + } + } + } + + when { + process { + """ + input[0] = "lukas" + input[1] = GENERATE_DATA.out.results + """ + } + } + + then { + assert process.success + assert snapshot(process.out.results).match() + } + } + +} diff --git a/test-data/process/dependencies/process_data.nf.test.snap b/test-data/process/dependencies/process_data.nf.test.snap new file mode 100644 index 00000000..4f08e5b0 --- /dev/null +++ b/test-data/process/dependencies/process_data.nf.test.snap @@ -0,0 +1,10 @@ +{ + "Should use process GENERATE_DATA to generate input data": { + "content": [ + [ + "output.txt:md5,cf78c141ba07d58cba270f3ccc5ee358" + ] + ], + "timestamp": "2023-10-05T12:41:15.52647" + } +} \ No newline at end of file