From 18f53949ea4f6128ec8505a30bffcd0d0d757879 Mon Sep 17 00:00:00 2001 From: Lukas Forer Date: Mon, 29 Jan 2024 13:07:10 +0100 Subject: [PATCH 1/2] Add property to set alias for dependencies (#183) * Add alias to dependencies * Fix merging problem in ProcessTest * Fix merging problem in ProcessTest * Add basic documentation for aliasing --- docs/docs/testcases/setup.md | 69 +++++++++++++++++++ .../com/askimed/nf/test/lang/Dependency.java | 23 ++++++- .../nf/test/lang/process/ProcessContext.java | 10 ++- .../test/lang/workflow/WorkflowContext.java | 10 ++- .../nf/test/lang/process/WorkflowMock.nf | 4 +- .../nf/test/lang/workflow/WorkflowMock.nf | 4 +- .../com/askimed/nf/test/lang/ProcessTest.java | 12 +++- .../dependencies/process_data_alias.nf.test | 36 ++++++++++ 8 files changed, 157 insertions(+), 11 deletions(-) create mode 100644 test-data/process/dependencies/process_data_alias.nf.test diff --git a/docs/docs/testcases/setup.md b/docs/docs/testcases/setup.md index d58d070c..719d1143 100644 --- a/docs/docs/testcases/setup.md +++ b/docs/docs/testcases/setup.md @@ -38,6 +38,17 @@ run("WorkflowName") { } ``` +If you need to run the same process multiple times, you can set the alias of the process: + +```groovy +run("GENERATE_DATA", alias: "MY_PROCESS") { + script "./generate_data.nf" + process { + ... + } +} +``` + !!! 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. @@ -153,3 +164,61 @@ nextflow_process { } ``` +### 3. Aliasing of Dependencies + +In this example, the process `UNTAR` is used multiple times in the setup method: + +```groovy +nextflow_process { + + ... + + setup { + + run("UNTAR", alias: "UNTAR1") { + script "modules/nf-core/untar/main.nf" + process { + """ + input[0] = Channel.fromList(...) + """ + } + } + + run("UNTAR", alias: "UNTAR2") { + script "modules/nf-core/untar/main.nf" + process { + """ + input[0] = Channel.fromList(...) + """ + } + } + + run("UNTAR", alias: "UNTAR3") { + script "modules/nf-core/untar/main.nf" + process { + """ + input[0] = Channel.fromList(...) + """ + } + } + } + + test("Test with three different inputs") { + when { + process { + """ + input[0] = UNTAR1.out.untar.map{ it[1] } + input[1] = UNTAR2.out.untar.map{ it[1] } + input[2] = UNTAR3.out.untar.map{ it[1] } + """ + } + } + + then { + ... + } + + } + +} +``` \ No newline at end of file diff --git a/src/main/java/com/askimed/nf/test/lang/Dependency.java b/src/main/java/com/askimed/nf/test/lang/Dependency.java index 1a274e4a..8c83ab25 100644 --- a/src/main/java/com/askimed/nf/test/lang/Dependency.java +++ b/src/main/java/com/askimed/nf/test/lang/Dependency.java @@ -2,16 +2,25 @@ import groovy.lang.Closure; +import java.util.Map; + public class Dependency { private String script; private String name; + private String alias; + private String mapping; - public Dependency(String name, Closure closure) { + public static final String ATTRIBUTE_ALIAS = "alias"; + + public Dependency(String name, Map attributes, Closure closure) { this.name = name; + if (attributes.containsKey(ATTRIBUTE_ALIAS)) { + this.alias = attributes.get(ATTRIBUTE_ALIAS).toString(); + } closure.setDelegate(this); closure.setResolveStrategy(Closure.DELEGATE_FIRST); closure.call(); @@ -54,6 +63,18 @@ public void setName(String name) { this.name = name; } + public String getAlias() { + return alias; + } + + public void setAlias(String alias) { + this.alias = alias; + } + + public boolean hasAlias() { + return alias != null; + } + public String getMapping() { return 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 8f22ce90..f4189467 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,8 @@ package com.askimed.nf.test.lang.process; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.Vector; import com.askimed.nf.test.core.ITest; @@ -50,11 +52,15 @@ public void evaluateProcessClosure() { } - public void run(String process, Closure closure) { - Dependency dependency = new Dependency(process, closure); + public void run(Map attributes, String process, Closure closure) { + Dependency dependency = new Dependency(process, attributes, closure); dependencies.add(dependency); } + public void run(String process, Closure closure) { + run(new LinkedHashMap(), process, closure); + } + public List getDependencies() { return dependencies; } 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 a9ae6efc..babb26ff 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,8 @@ package com.askimed.nf.test.lang.workflow; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.Vector; import com.askimed.nf.test.core.ITest; @@ -46,11 +48,15 @@ public void setWorkflow(Workflow workflow) { this.workflow = workflow; } - public void run(String process, Closure closure) { - Dependency dependency = new Dependency(process, closure); + public void run(Map attributes, String process, Closure closure) { + Dependency dependency = new Dependency(process, attributes, closure); dependencies.add(dependency); } + public void run(String process, Closure closure) { + run(new LinkedHashMap(), process, closure); + } + public List getDependencies() { return dependencies; } 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 fed530ce..d006888e 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 @@ -8,7 +8,7 @@ params.nf_test_output = "" // include dependencies <% for (dependency in dependencies) { %> -include { ${dependency.name} } from '${dependency.script}' +include { ${dependency.name} ${dependency.hasAlias() ? " as " + dependency.alias : "" } } from '${dependency.script}' <% } %> // include test process @@ -29,7 +29,7 @@ workflow { { def input = [] ${dependency.mapping} - ${dependency.name}(*input) + ${dependency.hasAlias() ? dependency.alias : dependency.name}(*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 d2fd28c9..126157ca 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 @@ -8,7 +8,7 @@ params.nf_test_output = "" // include dependencies <% for (dependency in dependencies) { %> -include { ${dependency.name} } from '${dependency.script}' +include { ${dependency.name} ${dependency.hasAlias() ? " as " + dependency.alias : "" } } from '${dependency.script}' <% } %> // include test workflow @@ -29,7 +29,7 @@ workflow { { def input = [] ${dependency.mapping} - ${dependency.name}(*input) + ${dependency.hasAlias() ? dependency.alias : dependency.name}(*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 1013cee5..a52ae989 100644 --- a/src/test/java/com/askimed/nf/test/lang/ProcessTest.java +++ b/src/test/java/com/askimed/nf/test/lang/ProcessTest.java @@ -221,9 +221,17 @@ public void testScriptWithRelativePathInSubfolder() throws Exception { public void testDependencies() throws Exception { App app = new App(); - int exitCode = app.run(new String[] { "test", "test-data/process/dependencies/process_data.nf.test" }); + int exitCode = app.run(new String[] { "test", "test-data/process/dependencies/process_data.nf.test", "--verbose" }); - } + } + + @Test + public void testDependenciesWithAlias() throws Exception { + + App app = new App(); + int exitCode = app.run(new String[] { "test", "test-data/process/dependencies/process_data_alias.nf.test", "--verbose" }); + + } @Test public void testDependenciesAbricate() throws Exception { diff --git a/test-data/process/dependencies/process_data_alias.nf.test b/test-data/process/dependencies/process_data_alias.nf.test new file mode 100644 index 00000000..46556cfe --- /dev/null +++ b/test-data/process/dependencies/process_data_alias.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 with alias PROCESS_ALIAS to generate input data") { + + setup { + run("GENERATE_DATA", alias: "LUKAS") { + script "./generate_data.nf" + process { + """ + input[0] = "nf-core" + """ + } + } + } + + when { + process { + """ + input[0] = "lukas" + input[1] = LUKAS.out.results + """ + } + } + + then { + assert process.success + assert snapshot(process.out.results).match() + } + } + +} From 17ffed3f092dac8a2d9aaff5ee4364dfa589aa25 Mon Sep 17 00:00:00 2001 From: Lukas Forer Date: Tue, 30 Jan 2024 15:11:45 +0100 Subject: [PATCH 2/2] Handle File objects correctly in snapshots (#194) --- .../askimed/nf/test/lang/extensions/util/PathConverter.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/com/askimed/nf/test/lang/extensions/util/PathConverter.java b/src/main/java/com/askimed/nf/test/lang/extensions/util/PathConverter.java index 47d1d56f..4b254b00 100644 --- a/src/main/java/com/askimed/nf/test/lang/extensions/util/PathConverter.java +++ b/src/main/java/com/askimed/nf/test/lang/extensions/util/PathConverter.java @@ -26,6 +26,11 @@ public Object convert(Object value, String key) { if (!path.toFile().exists()) { throw new RuntimeException("Path " + path.toString() + " not found."); } + } else if (value instanceof File) { + path = ((File) value).toPath(); + if (!path.toFile().exists()) { + throw new RuntimeException("Path " + path.toString() + " not found."); + } } else { path = new File(value.toString()).toPath();