From 84cf75ddf41bf3e19d420c6e2d847aa3cf4f8889 Mon Sep 17 00:00:00 2001 From: Andreas Schmid Date: Fri, 30 Mar 2018 22:45:39 +0200 Subject: [PATCH] support to specify a test name formatter on @DataProvider annotation (#101) Signed-off-by: Andreas Schmid --- .../dataprovider/FormatAcceptanceTest.java | 33 +++++++++++++++++++ .../junit/dataprovider/DataProvider.java | 10 ++++++ .../dataprovider/DataProviderExtension.java | 2 +- .../DataProviderInvocationContext.java | 15 +++++---- .../dataprovider/DisplayNameContext.java | 12 +++++++ .../UseDataProviderExtension.java | 2 +- ...DataProviderInvocationContextProvider.java | 1 + .../DataProviderPlaceholderFormatter.java | 29 ++++++++++++++++ .../format/DataProviderTestNameFormatter.java | 9 +++++ 9 files changed, 104 insertions(+), 9 deletions(-) create mode 100644 junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/format/DataProviderPlaceholderFormatter.java create mode 100644 junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/format/DataProviderTestNameFormatter.java diff --git a/junit-jupiter/src/integTest/java/com/tngtech/test/junit/dataprovider/FormatAcceptanceTest.java b/junit-jupiter/src/integTest/java/com/tngtech/test/junit/dataprovider/FormatAcceptanceTest.java index 94bec564..b03e17e6 100644 --- a/junit-jupiter/src/integTest/java/com/tngtech/test/junit/dataprovider/FormatAcceptanceTest.java +++ b/junit-jupiter/src/integTest/java/com/tngtech/test/junit/dataprovider/FormatAcceptanceTest.java @@ -2,6 +2,9 @@ import static org.assertj.core.api.Assertions.assertThat; +import java.lang.reflect.Method; +import java.util.List; + import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.ExtendWith; @@ -9,10 +12,40 @@ import com.tngtech.junit.dataprovider.DataProvider; import com.tngtech.junit.dataprovider.UseDataProvider; import com.tngtech.junit.dataprovider.UseDataProviderExtension; +import com.tngtech.junit.dataprovider.format.DataProviderTestNameFormatter; @ExtendWith(UseDataProviderExtension.class) class FormatAcceptanceTest { + static class PlusTestNameFormatter implements DataProviderTestNameFormatter { + @Override + public String format(Method testMethod, int invocationIndex, List arguments) { + return String.format("%s: %2d + %2d = %2d", testMethod.getName(), arguments.get(0), arguments.get(1), + arguments.get(2)); + } + } + + @DataProvider(format = "%a[0] * %a[1] == %a[2]", formatter = PlusTestNameFormatter.class) + static Object[][] dataProviderPlus() { + // @formatter:off + return new Object[][] { + { 0, 0, 0 }, + { -1, 0, -1 }, + { 0, 1, 1 }, + { 1, 1, 2 }, + { 1, -1, 0 }, + { -1, -1, -2 }, + }; + // @formatter:on + } + + @TestTemplate + @UseDataProvider + void testPlus(int a, int b, int expected) { + // Expect: + assertThat(a + b).isEqualTo(expected); + } + @DataProvider(format = "%a[0] * %a[1] == %a[2]") static Object[][] dataProviderMultiply() { // @formatter:off diff --git a/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/DataProvider.java b/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/DataProvider.java index 3163f1d9..ebc86916 100644 --- a/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/DataProvider.java +++ b/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/DataProvider.java @@ -12,6 +12,8 @@ import com.tngtech.junit.dataprovider.convert.ObjectArrayConverter; import com.tngtech.junit.dataprovider.convert.SingleArgConverter; import com.tngtech.junit.dataprovider.convert.StringConverter; +import com.tngtech.junit.dataprovider.format.DataProviderPlaceholderFormatter; +import com.tngtech.junit.dataprovider.format.DataProviderTestNameFormatter; /** * Mark a method as a dataprovider used by a test method or use it directly at the test method and provide data via {@link #value()} @@ -199,6 +201,14 @@ */ String format() default DEFAULT_FORMAT; + /** + * Formatter to be used to generate test method description. The placeholder approach which formats according to + * {@link #format()} is used by default. + * + * @return a formatter used to generate test names. + */ + Class formatter() default DataProviderPlaceholderFormatter.class; + /** * @return a custom converter converting {@link Object}{@code []} data to proper arguments * @see ObjectArrayConverter diff --git a/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/DataProviderExtension.java b/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/DataProviderExtension.java index cc3049db..30d2610d 100644 --- a/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/DataProviderExtension.java +++ b/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/DataProviderExtension.java @@ -28,6 +28,6 @@ protected ConverterContext getConverterContext(DataProvider dataProvider) { @Override protected DisplayNameContext getDisplayNameContext(DataProvider dataProvider) { - return new DisplayNameContext(dataProvider.format(), getDefaultPlaceholders()); + return new DisplayNameContext(dataProvider.formatter(), dataProvider.format(), getDefaultPlaceholders()); } } diff --git a/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/DataProviderInvocationContext.java b/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/DataProviderInvocationContext.java index 6ca50223..61ba44af 100644 --- a/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/DataProviderInvocationContext.java +++ b/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/DataProviderInvocationContext.java @@ -9,9 +9,9 @@ import org.junit.jupiter.api.extension.Extension; import org.junit.jupiter.api.extension.TestTemplateInvocationContext; +import org.junit.platform.commons.util.ReflectionUtils; -import com.tngtech.junit.dataprovider.placeholder.BasePlaceholder; -import com.tngtech.junit.dataprovider.placeholder.ReplacementData; +import com.tngtech.junit.dataprovider.format.DataProviderPlaceholderFormatter; class DataProviderInvocationContext implements TestTemplateInvocationContext { @@ -27,13 +27,14 @@ class DataProviderInvocationContext implements TestTemplateInvocationContext { @Override public String getDisplayName(int invocationIndex) { - ReplacementData data = ReplacementData.of(testMethod, invocationIndex, arguments); - String result = displayNameContext.getFormat(); - for (BasePlaceholder placeHolder : displayNameContext.getPlaceholders()) { - result = placeHolder.process(data, result); + if (displayNameContext.getFormatter() == null + || DataProviderPlaceholderFormatter.class.equals(displayNameContext.getFormatter())) { + return new DataProviderPlaceholderFormatter(displayNameContext.getFormat(), + displayNameContext.getPlaceholders()).format(testMethod, invocationIndex, arguments); } - return result; + return ReflectionUtils.newInstance(displayNameContext.getFormatter()).format(testMethod, invocationIndex, + arguments); } @Override diff --git a/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/DisplayNameContext.java b/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/DisplayNameContext.java index f25054cf..149b4d76 100644 --- a/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/DisplayNameContext.java +++ b/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/DisplayNameContext.java @@ -6,18 +6,30 @@ import java.util.ArrayList; import java.util.List; +import com.tngtech.junit.dataprovider.format.DataProviderTestNameFormatter; import com.tngtech.junit.dataprovider.placeholder.BasePlaceholder; public class DisplayNameContext { + private final Class formatter; private final String format; private final List placeholders; public DisplayNameContext(String format, List placeholders) { + this(null, format, placeholders); + } + + public DisplayNameContext(Class formatter, String format, + List placeholders) { + this.formatter = formatter; this.format = checkNotNull(format, "'format' must not be null"); this.placeholders = new ArrayList<>(checkNotNull(placeholders, "'placeholders' must not be null")); } + public Class getFormatter() { + return formatter; + } + public String getFormat() { return format; } diff --git a/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/UseDataProviderExtension.java b/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/UseDataProviderExtension.java index 78ad6f39..cf7380f4 100644 --- a/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/UseDataProviderExtension.java +++ b/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/UseDataProviderExtension.java @@ -42,6 +42,6 @@ protected boolean cacheDataProviderResult(DataProvider dataProviderAnnotation) { @Override protected DisplayNameContext getDisplayNameContext(DataProvider dataProvider) { - return new DisplayNameContext(dataProvider.format(), getDefaultPlaceholders()); + return new DisplayNameContext(dataProvider.formatter(), dataProvider.format(), getDefaultPlaceholders()); } } diff --git a/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/UseDataProviderInvocationContextProvider.java b/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/UseDataProviderInvocationContextProvider.java index 10a639e0..50044577 100644 --- a/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/UseDataProviderInvocationContextProvider.java +++ b/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/UseDataProviderInvocationContextProvider.java @@ -23,6 +23,7 @@ import com.tngtech.junit.dataprovider.convert.ConverterContext; import com.tngtech.junit.dataprovider.convert.DataConverter; +import com.tngtech.junit.dataprovider.format.DataProviderTestNameFormatter; import com.tngtech.junit.dataprovider.resolver.DataProviderResolverContext; /** diff --git a/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/format/DataProviderPlaceholderFormatter.java b/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/format/DataProviderPlaceholderFormatter.java new file mode 100644 index 00000000..05817afd --- /dev/null +++ b/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/format/DataProviderPlaceholderFormatter.java @@ -0,0 +1,29 @@ +package com.tngtech.junit.dataprovider.format; + +import java.lang.reflect.Method; +import java.util.List; + +import com.tngtech.junit.dataprovider.placeholder.BasePlaceholder; +import com.tngtech.junit.dataprovider.placeholder.ReplacementData; + +public class DataProviderPlaceholderFormatter implements DataProviderTestNameFormatter { + + private final String format; + private final List placeholders; + + public DataProviderPlaceholderFormatter(String format, List placeholders) { + this.format = format; + this.placeholders = placeholders; + } + + @Override + public String format(Method testMethod, int invocationIndex, List arguments) { + ReplacementData data = ReplacementData.of(testMethod, invocationIndex, arguments); + + String result = format; + for (BasePlaceholder placeHolder : placeholders) { + result = placeHolder.process(data, result); + } + return result; + } +} diff --git a/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/format/DataProviderTestNameFormatter.java b/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/format/DataProviderTestNameFormatter.java new file mode 100644 index 00000000..b8e7952b --- /dev/null +++ b/junit-jupiter/src/main/java/com/tngtech/junit/dataprovider/format/DataProviderTestNameFormatter.java @@ -0,0 +1,9 @@ +package com.tngtech.junit.dataprovider.format; + +import java.lang.reflect.Method; +import java.util.List; + +public interface DataProviderTestNameFormatter { + + String format(Method testMethod, int invocationIndex, List arguments); +}