diff --git a/flytekit-testing/src/main/java/org/flyte/flytekit/testing/TestingRunnableNode.java b/flytekit-testing/src/main/java/org/flyte/flytekit/testing/TestingRunnableNode.java index 2df1b28b7..b16e16d63 100644 --- a/flytekit-testing/src/main/java/org/flyte/flytekit/testing/TestingRunnableNode.java +++ b/flytekit-testing/src/main/java/org/flyte/flytekit/testing/TestingRunnableNode.java @@ -20,7 +20,9 @@ import java.util.HashMap; import java.util.Map; +import java.util.Objects; import java.util.function.Function; +import java.util.stream.Collectors; import org.flyte.api.v1.Literal; import org.flyte.api.v1.PartialIdentifier; import org.flyte.api.v1.RunnableNode; @@ -84,7 +86,7 @@ protected TestingRunnableNode( public Map run(Map inputs) { InputT input = inputType.fromLiteralMap(inputs); - if (fixedOutputs.size() == 0) { + if (fixedOutputs.isEmpty()) { // No mocking via input matching, either run the real thing or run the provided lambda if (runFn != null) { return outputType.toLiteralMap(runFn.apply(input)); @@ -101,14 +103,31 @@ public Map run(Map inputs) { String message = String.format( - "Can't find input %s for remote %s [%s] across known %s inputs, " - + "use %s to provide a test double", - input, type, getName(), type, testingSuggestion); + "Can't find input for remote %s [%s] across known %s inputs.%s", + type, getName(), type, System.lineSeparator()) + + String.format( + "Input: %s%sKnown inputs: %s%sUse %s to provide a test double", + input, + System.lineSeparator(), + knownInputsString(), + System.lineSeparator(), + testingSuggestion); // Not matching inputs and there is nothing to run throw new IllegalArgumentException(message); } + private String knownInputsString() { + String knownInputs = + fixedOutputs.keySet().stream() + .map(Objects::toString) + .collect(Collectors.joining(System.lineSeparator())); + if (knownInputs.isEmpty()) { + return "{}"; + } + return knownInputs; + } + @Override public String getName() { return id.name(); diff --git a/flytekit-testing/src/test/java/org/flyte/flytekit/testing/SdkTestingExecutorTest.java b/flytekit-testing/src/test/java/org/flyte/flytekit/testing/SdkTestingExecutorTest.java index c07a63590..25b2503e2 100644 --- a/flytekit-testing/src/test/java/org/flyte/flytekit/testing/SdkTestingExecutorTest.java +++ b/flytekit-testing/src/test/java/org/flyte/flytekit/testing/SdkTestingExecutorTest.java @@ -253,7 +253,10 @@ public Void expand(SdkWorkflowBuilder builder, Void noInput) { assertThat( e.getMessage(), equalTo( - "Can't find input RemoteSumInput{a=SdkBindingData{type=integers, value=1}, b=SdkBindingData{type=integers, value=2}} for remote task [remote_sum_task] across known task inputs, use SdkTestingExecutor#withTaskOutput or SdkTestingExecutor#withTask to provide a test double")); + "Can't find input for remote task [remote_sum_task] across known task inputs.\n" + + "Input: RemoteSumInput{a=SdkBindingData{type=integers, value=1}, b=SdkBindingData{type=integers, value=2}}\n" + + "Known inputs: RemoteSumInput{a=SdkBindingData{type=integers, value=10}, b=SdkBindingData{type=integers, value=20}}\n" + + "Use SdkTestingExecutor#withTaskOutput or SdkTestingExecutor#withTask to provide a test double")); } @Test @@ -383,7 +386,10 @@ public TestUnaryIntegerIO expand(SdkWorkflowBuilder builder, SumLaunchPlanInput assertThat( ex.getMessage(), equalTo( - "Can't find input SumLaunchPlanInput{a=SdkBindingData{type=integers, value=3}, b=SdkBindingData{type=integers, value=5}} for remote launch plan [SumWorkflow] across known launch plan inputs, use SdkTestingExecutor#withLaunchPlanOutput or SdkTestingExecutor#withLaunchPlan to provide a test double")); + "Can't find input for remote launch plan [SumWorkflow] across known launch plan inputs." + + "\nInput: SumLaunchPlanInput{a=SdkBindingData{type=integers, value=3}, b=SdkBindingData{type=integers, value=5}}" + + "\nKnown inputs: SumLaunchPlanInput{a=SdkBindingData{type=integers, value=100000}, b=SdkBindingData{type=integers, value=100000}}" + + "\nUse SdkTestingExecutor#withLaunchPlanOutput or SdkTestingExecutor#withLaunchPlan to provide a test double")); } @Test @@ -504,7 +510,10 @@ public Void expand(SdkWorkflowBuilder builder, Void noInput) { assertThat( e.getMessage(), equalTo( - "Can't find input RemoteSumInput{a=SdkBindingData{type=integers, value=1}, b=SdkBindingData{type=integers, value=2}} for remote task [remote_sum_task] across known task inputs, use SdkTestingExecutor#withTaskOutput or SdkTestingExecutor#withTask to provide a test double")); + "Can't find input for remote task [remote_sum_task] across known task inputs.\n" + + "Input: RemoteSumInput{a=SdkBindingData{type=integers, value=1}, b=SdkBindingData{type=integers, value=2}}\n" + + "Known inputs: RemoteSumInput{a=SdkBindingData{type=integers, value=10}, b=SdkBindingData{type=integers, value=20}}\n" + + "Use SdkTestingExecutor#withTaskOutput or SdkTestingExecutor#withTask to provide a test double")); } public static class SimpleUberWorkflow diff --git a/flytekit-testing/src/test/java/org/flyte/flytekit/testing/TestingRunnableNodeTest.java b/flytekit-testing/src/test/java/org/flyte/flytekit/testing/TestingRunnableNodeTest.java index d8b7501e6..d845648fb 100644 --- a/flytekit-testing/src/test/java/org/flyte/flytekit/testing/TestingRunnableNodeTest.java +++ b/flytekit-testing/src/test/java/org/flyte/flytekit/testing/TestingRunnableNodeTest.java @@ -21,6 +21,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasEntry; +import static org.hamcrest.Matchers.oneOf; import static org.junit.jupiter.api.Assertions.assertThrows; import com.google.auto.value.AutoValue; @@ -70,7 +71,10 @@ void testRun_preferStubValuesOverFunction() { @Test void testRun_notFound() { - Map fixedOutputs = singletonMap(Input.create("7"), Output.create(7L)); + Map fixedOutputs = + Map.of( + Input.create("7"), Output.create(7L), + Input.create("8"), Output.create(8L)); TestNode node = new TestNode(null, fixedOutputs); IllegalArgumentException ex = @@ -80,9 +84,17 @@ void testRun_notFound() { assertThat( ex.getMessage(), - equalTo( - "Can't find input Input{in=SdkBindingData{type=strings, value=not in fixed outputs}} for remote test [TestTask] " - + "across known test inputs, use a magic wang to provide a test double")); + oneOf( + "Can't find input for remote test [TestTask] across known test inputs.\n" + + "Input: Input{in=SdkBindingData{type=strings, value=not in fixed outputs}}\n" + + "Known inputs: Input{in=SdkBindingData{type=strings, value=8}}\n" + + "Input{in=SdkBindingData{type=strings, value=7}}\n" + + "Use a magic wang to provide a test double", + "Can't find input for remote test [TestTask] across known test inputs.\n" + + "Input: Input{in=SdkBindingData{type=strings, value=not in fixed outputs}}\n" + + "Known inputs: Input{in=SdkBindingData{type=strings, value=7}}\n" + + "Input{in=SdkBindingData{type=strings, value=8}}\n" + + "Use a magic wang to provide a test double")); } @Test @@ -128,8 +140,10 @@ void testWithoutRunFn() { assertThat( ex.getMessage(), equalTo( - "Can't find input Input{in=SdkBindingData{type=strings, value=7}} for remote test [TestTask] " - + "across known test inputs, use a magic wang to provide a test double")); + "Can't find input for remote test [TestTask] across known test inputs.\n" + + "Input: Input{in=SdkBindingData{type=strings, value=7}}\n" + + "Known inputs: {}\n" + + "Use a magic wang to provide a test double")); } @Test