Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add names for parameterized tests. Fixes #24 and #44.

In order that you can easily identify individual test, you may provide
a name for the Parameters annotation.
 @Parameters(name="my test")
This name is allowed to contain placeholders, which are replaced at
runtime. The placeholders are
* {index} - the current parameter index
* {0} - the first parameter
* {1} - the second parameter
* ... - the other parameters
If you don't use the name parameter, then the current parameter index
is used as name.

Example:
When you use @Parameters(name="fib({0})={1}") with the Fibonacci
example, then you get test names like "fib(3)=2".

This feature is based on the work of Dimitar Dimitrov (pull request
#145).
Thank
you.
  • Loading branch information...
commit e0cddcdfa8ec823da136af500cce0910a1dd2264 1 parent 1cec456
@stefanbirkner stefanbirkner authored
View
105 src/main/java/org/junit/runners/Parameterized.java
@@ -1,12 +1,13 @@
package org.junit.runners;
-import static java.lang.String.format;
+import static java.text.MessageFormat.format;
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -29,7 +30,7 @@
* <pre>
* &#064;RunWith(Parameterized.class)
* public class FibonacciTest {
- * &#064;Parameters
+ * &#064;Parameters(name= &quot;fib({0})={1}&quot;)
* public static Iterable&lt;Object[]&gt; data() {
* return Arrays.asList(new Object[][] { { 0, 0 }, { 1, 1 }, { 2, 1 },
* { 3, 2 }, { 4, 3 }, { 5, 5 }, { 6, 8 } });
@@ -55,6 +56,24 @@
* Each instance of <code>FibonacciTest</code> will be constructed using the
* two-argument constructor and the data values in the
* <code>&#064;Parameters</code> method.
+ *
+ * <p>
+ * In order that you can easily identify the individual tests, you may provide a
+ * name for the <code>&#064;Parameters</code> annotation. This name is allowed
+ * to contain placeholders, which are replaced at runtime. The placeholders are
+ * <dl>
+ * <dt>{index}</dt>
+ * <dd>the current parameter index</dd>
+ * <dt>{0}</dt>
+ * <dd>the first parameter value</dd>
+ * <dt>{1}</dt>
+ * <dd>the second parameter value</dd>
+ * <dt>...</dt>
+ * <dd></dd>
+ * </dl>
+ * In the example given above, the <code>Parameterized</code> runner creates
+ * names like <code>fib(3)=2</code>. If you don't use the name parameter, then
+ * the current parameter index is used as name.
* </p>
*/
public class Parameterized extends Suite {
@@ -65,19 +84,41 @@
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public static @interface Parameters {
+ /**
+ * <p>
+ * Optional pattern to derive the test's name from the parameters. Use
+ * numbers in braces to refer to the parameters or the additional data
+ * as follows:
+ * </p>
+ *
+ * <pre>
+ * {index} - the current parameter index
+ * {0} - the first parameter value
+ * {1} - the second parameter value
+ * etc...
+ * </pre>
+ * <p>
+ * Default value is "[{index}]" for compatibility with previous JUnit
+ * versions.
+ * </p>
+ *
+ * @return {@link MessageFormat} pattern string, except the index
+ * placeholder.
+ * @see MessageFormat
+ */
+ String name() default "[{index}]";
}
- private class TestClassRunnerForParameters extends
- BlockJUnit4ClassRunner {
- private final int fParameterSetNumber;
-
+ private class TestClassRunnerForParameters extends BlockJUnit4ClassRunner {
private final Object[] fParameters;
- TestClassRunnerForParameters(Class<?> type, Object[] parameters, int i)
- throws InitializationError {
+ private final String fName;
+
+ TestClassRunnerForParameters(Class<?> type, Object[] parameters,
+ String name) throws InitializationError {
super(type);
fParameters= parameters;
- fParameterSetNumber= i;
+ fName= name;
}
@Override
@@ -87,13 +128,12 @@ public Object createTest() throws Exception {
@Override
protected String getName() {
- return String.format("[%s]", fParameterSetNumber);
+ return fName;
}
@Override
- protected String testName(final FrameworkMethod method) {
- return String.format("%s[%s]", method.getName(),
- fParameterSetNumber);
+ protected String testName(FrameworkMethod method) {
+ return method.getName() + getName();
}
@Override
@@ -105,22 +145,26 @@ protected void validateConstructor(List<Throwable> errors) {
protected Statement classBlock(RunNotifier notifier) {
return childrenInvoker(notifier);
}
-
+
@Override
protected Annotation[] getRunnerAnnotations() {
return new Annotation[0];
}
}
+ private static final List<Runner> NO_RUNNERS= Collections
+ .<Runner> emptyList();
+
private final ArrayList<Runner> runners= new ArrayList<Runner>();
/**
* Only called reflectively. Do not use programmatically.
*/
public Parameterized(Class<?> klass) throws Throwable {
- super(klass, Collections.<Runner> emptyList());
- Iterable<Object[]> allParameters= getAllParameters();
- createRunnersForParameters(allParameters);
+ super(klass, NO_RUNNERS);
+ Parameters parameters= getParametersMethod().getAnnotation(
+ Parameters.class);
+ createRunnersForParameters(allParameters(), parameters.name());
}
@Override
@@ -129,8 +173,7 @@ public Parameterized(Class<?> klass) throws Throwable {
}
@SuppressWarnings("unchecked")
- private Iterable<Object[]> getAllParameters()
- throws Throwable {
+ private Iterable<Object[]> allParameters() throws Throwable {
Object parameters= getParametersMethod().invokeExplosively(null);
if (parameters instanceof Iterable)
return (Iterable<Object[]>) parameters;
@@ -138,10 +181,9 @@ public Parameterized(Class<?> klass) throws Throwable {
throw parametersMethodReturnedWrongType();
}
- private FrameworkMethod getParametersMethod()
- throws Exception {
- List<FrameworkMethod> methods= getTestClass()
- .getAnnotatedMethods(Parameters.class);
+ private FrameworkMethod getParametersMethod() throws Exception {
+ List<FrameworkMethod> methods= getTestClass().getAnnotatedMethods(
+ Parameters.class);
for (FrameworkMethod each : methods) {
if (each.isStatic() && each.isPublic())
return each;
@@ -151,14 +193,15 @@ private FrameworkMethod getParametersMethod()
+ getTestClass().getName());
}
- private void createRunnersForParameters(Iterable<Object[]> allParameters)
- throws InitializationError, Exception {
+ private void createRunnersForParameters(Iterable<Object[]> allParameters,
+ String namePattern) throws InitializationError, Exception {
try {
int i= 0;
for (Object[] parametersOfSingleTest : allParameters) {
+ String name= nameFor(namePattern, i, parametersOfSingleTest);
TestClassRunnerForParameters runner= new TestClassRunnerForParameters(
getTestClass().getJavaClass(), parametersOfSingleTest,
- i);
+ name);
runners.add(runner);
++i;
}
@@ -167,11 +210,17 @@ private void createRunnersForParameters(Iterable<Object[]> allParameters)
}
}
+ private String nameFor(String namePattern, int index, Object[] parameters) {
+ String finalPattern= namePattern.replaceAll("\\{index\\}",
+ Integer.toString(index));
+ return format(finalPattern, parameters);
+ }
+
private Exception parametersMethodReturnedWrongType() throws Exception {
String className= getTestClass().getName();
String methodName= getParametersMethod().getName();
- String message= format("%s.%s() must return an Iterable of arrays.",
+ String message= format("{0}.{1}() must return an Iterable of arrays.",
className, methodName);
return new Exception(message);
}
-}
+}
View
36 src/test/java/org/junit/tests/running/classes/ParameterizedTestTest.java
@@ -25,15 +25,15 @@
public class ParameterizedTestTest {
@RunWith(Parameterized.class)
static public class FibonacciTest {
- @Parameters
+ @Parameters(name= "[{index}: fib({0})={1}]")
public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][] { { 0, 0 }, { 1, 1 }, { 2, 1 },
{ 3, 2 }, { 4, 3 }, { 5, 5 }, { 6, 8 } });
}
- private int fInput;
+ private final int fInput;
- private int fExpected;
+ private final int fExpected;
public FibonacciTest(int input, int expected) {
fInput= input;
@@ -61,7 +61,7 @@ public void count() {
public void failuresNamedCorrectly() {
Result result= JUnitCore.runClasses(FibonacciTest.class);
assertEquals(
- String.format("test[1](%s)", FibonacciTest.class.getName()),
+ "test[1: fib(1)=1](" + FibonacciTest.class.getName() + ")",
result.getFailures().get(0).getTestHeader());
}
@@ -75,7 +75,31 @@ public void countBeforeRun() throws Exception {
public void plansNamedCorrectly() throws Exception {
Runner runner= Request.aClass(FibonacciTest.class).getRunner();
Description description= runner.getDescription();
- assertEquals("[0]", description.getChildren().get(0).getDisplayName());
+ assertEquals("[0: fib(0)=0]", description.getChildren().get(0)
+ .getDisplayName());
+ }
+
+ @RunWith(Parameterized.class)
+ public static class ParameterizedWithoutSpecialTestname {
+ @Parameters
+ public static Collection<Object[]> data() {
+ return Arrays.asList(new Object[][] { { 3 }, { 3 } });
+ }
+
+ public ParameterizedWithoutSpecialTestname(Object something) {
+ }
+
+ @Test
+ public void testSomething() {
+ }
+ }
+
+ @Test
+ public void usesIndexAsTestName() {
+ Runner runner= Request
+ .aClass(ParameterizedWithoutSpecialTestname.class).getRunner();
+ Description description= runner.getDescription();
+ assertEquals("[1]", description.getChildren().get(1).getDisplayName());
}
private static String fLog;
@@ -230,4 +254,4 @@ public void aTest() {
public void exceptionWhenPrivateConstructor() throws Throwable {
new Parameterized(PrivateConstructor.class);
}
-}
+}
Please sign in to comment.
Something went wrong with that request. Please try again.