Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Provide description patterns for Parameterized tests (addressing issues #24, #44 and #135) #145

Closed
wants to merge 1 commit into from

5 participants

@ddimtirov

Addresses issues #24, #44 and #135

Usually when using parameterized tests, the reports display [0], [1], [2] for each run of the fixture and methodName[0], methodName[1], etc. for the actual tests. This creates the situation where you need to lookup the actual parameters in the sources to see what is the actual failure. A better approach would be if we could customize display names to contain more information about the scenario we are running.

Here (http://github.com/ddimtirov/junit/commit/b99a3) is a forked version with patched Parameterized runner that achieves this and a basic test for the functionality. I've also added a basic test for illustration.

The new feature works by allowing one to specify fixtureDescription and testDescription patterns to the Parameters annotation. This has the benefit that the formatting is kept close to the data and the default values are chosen to be backwards compatible, so there is no impact to the users that choose not to specify the patterns. See Javadoc for details.

@neilsh

This is a great patch, has anyone with commit access taken a look at it yet?

@chadnickbok

This is an excellent patch! Right now, Parameterized test can't even be 'extended' to add this; the only way to do this is to completely re-implement Parameterized.java, or change it to allow further extension.

@ddimtirov

Updated the title to make it clear that the patch is fixing open issues, rather than proposal of new functionality.

@stefanbirkner

Please move this two fields to the TestClassRunnerForParameters.

Thanks for looking into this patch. Just letting you know that I do not use JUnit currently and do not have time to invest in tweaking this code.

Collaborator

That's okay. I take your patch and tweak it.

@stefanbirkner
Collaborator

Could you please rebase to master.

@dsaff
Owner

@stefanbirkner, where is your tweaked version?

@stefanbirkner
Collaborator

It is only in my mind, but I already have a bad conscience. I try to get it done as soon as possible.

@stefanbirkner
Collaborator

I started to finish this pull request on https://github.com/stefanbirkner/junit/tree/Parameterized

@stefanbirkner stefanbirkner referenced this pull request from a commit in stefanbirkner/junit
@stefanbirkner stefanbirkner 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.
e0cddcd
@stefanbirkner
Collaborator

@dsaff It's ready.

@ebruchez ebruchez referenced this pull request from a commit in orbeon/junit
@stefanbirkner stefanbirkner 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.
08c7053
@dsaff
Owner

@stefanbirkner, which is your pull request?

@stefanbirkner
Collaborator

It is #393.

@dsaff
Owner

Fixed, I believe, by #393

@dsaff dsaff closed this
@jherault jherault referenced this pull request from a commit
Commit has since been removed from the repository and is no longer available.
@gensan gensan referenced this pull request
Closed

Parameter's description #373

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
68 src/main/java/org/junit/runners/Parameterized.java
@@ -8,6 +8,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.text.MessageFormat;
import org.junit.runner.Runner;
import org.junit.runner.notification.RunNotifier;
@@ -60,12 +61,53 @@
*/
public class Parameterized extends Suite {
/**
+ * If parentheses are present in a fixture description, it is not reported
+ * correctly, so we should strip them for now.
+ */
+ private static final String PROBLEMATIC_FIXTURE_DESCRIPTION_CHARS = "\\(|\\)";
+
+ /**
* Annotation for a method which provides parameters to be injected into the
* test class constructor by <code>Parameterized</code>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public static @interface Parameters {
+ /**
+ * <p>Optional pattern to derive the fixture name from the parameters.
+ * Use numbers in braces to refer to the parameters or the additional
+ * data as follows:</p>
+ * <pre>
+ * {0} - the original fixture name
+ * {1} - the current parameter index
+ * {2} - the first parameter value
+ * {3} - the second parameter value
+ * etc...
+ * </pre>
+ * <p>Default value is "[{0}]" for compatibility with previous JUnit versions.</p>
+ *
+ * @return {@link MessageFormat} pattern string
+ * @see MessageFormat
+ */
+ String fixtureDescription() default "[{0}]";
+
+ /**
+ * <p>Optional pattern to derive the test name from the parameters.
+ * Use numbers in braces to refer to the parameters or the additional
+ * data as follows:</p>
+ * <pre>
+ * {0} - the original fixture name
+ * {1} - the current parameter index
+ * {2} - the first parameter value
+ * {3} - the second parameter value
+ * etc...
+ * </pre>
+ * <p>Default value is "{0}[{1}]" for compatibility with previous JUnit versions.</p>
+ *
+ * @return {@link MessageFormat} pattern string
+ * @see MessageFormat
+ */
+ String testDescription() default "{0}[{1}]";
}
private class TestClassRunnerForParameters extends
@@ -100,13 +142,26 @@ public Object createTest() throws Exception {
@Override
protected String getName() {
- return String.format("[%s]", fParameterSetNumber);
+ String str = calculateDescription(fixtureDescriptionFmt, super.getName());
+ return str.replaceAll(PROBLEMATIC_FIXTURE_DESCRIPTION_CHARS, "");
}
@Override
protected String testName(final FrameworkMethod method) {
- return String.format("%s[%s]", method.getName(),
- fParameterSetNumber);
+ return calculateDescription(testDescriptionFmt, method.getName());
+ }
+
+ private String calculateDescription(MessageFormat descriptionFmt, String name) {
+ try {
+ Object[] parameters = computeParams();
+ Object[] formatArgs = new Object[parameters.length + 2];
+ formatArgs[0] = name;
+ formatArgs[1] = fParameterSetNumber;
+ System.arraycopy(parameters, 0, formatArgs, 2, parameters.length);
+ return descriptionFmt.format(formatArgs, new StringBuffer(), null).toString();
+ } catch (Exception e) {
+ return String.format("[%s] ERR: %s", fParameterSetNumber, e.getMessage());
+ }
}
@Override
@@ -121,6 +176,8 @@ protected Statement classBlock(RunNotifier notifier) {
}
private final ArrayList<Runner> runners= new ArrayList<Runner>();
+ protected final MessageFormat fixtureDescriptionFmt;
+ protected final MessageFormat testDescriptionFmt;
/**
* Only called reflectively. Do not use programmatically.
@@ -131,6 +188,11 @@ public Parameterized(Class<?> klass) throws Throwable {
for (int i= 0; i < parametersList.size(); i++)
runners.add(new TestClassRunnerForParameters(getTestClass().getJavaClass(),
parametersList, i));
+
+ FrameworkMethod parametersMethod = getParametersMethod(getTestClass());
+ Parameters parameters = parametersMethod.getAnnotation(Parameters.class);
+ fixtureDescriptionFmt = new MessageFormat(parameters.fixtureDescription());
+ testDescriptionFmt = new MessageFormat(parameters.testDescription());
}
@Override
View
53 src/test/java/org/junit/tests/running/methods/NamedParameterizedTest.java
@@ -0,0 +1,53 @@
+package org.junit.tests.running.methods;
+
+import org.junit.Test;
+import org.junit.runner.Description;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.Assert.*;
+
+public class NamedParameterizedTest {
+ @RunWith(Parameterized.class)
+ static public class NamedFoobar {
+ @Parameters(fixtureDescription = "{0}[{1}] - ({3}, {2})", testDescription = "{0}[{1}]")
+ public static List<Object[]> params() {
+ return Arrays.asList(new Object[][]{
+ {"foo", 11}, {"bar", 22}, {"baz", 33}
+ });
+ }
+
+ private final String msg;
+ public NamedFoobar(String s, int i) { msg = s + i; }
+ @Test public void test1() {System.out.println("1:" + msg); }
+ @Test public void test2() {System.out.println("2:" + msg);}
+ }
+
+ @Test public void testFoobar() throws Throwable {
+ Parameterized foobar = new Parameterized(NamedFoobar.class);
+ String className = NamedFoobar.class.getName();
+
+ Description fixture = foobar.getDescription();
+ assertEquals(className, fixture.getDisplayName());
+
+ ArrayList<Description> parameterizedFixtures = fixture.getChildren();
+ assertEquals(parameterizedFixtures.size(), 3);
+ assertEquals(className + "[0] - 11, foo", parameterizedFixtures.get(0).getDisplayName());
+ assertEquals(className + "[1] - 22, bar", parameterizedFixtures.get(1).getDisplayName());
+ assertEquals(className + "[2] - 33, baz", parameterizedFixtures.get(2).getDisplayName());
+
+ int i = 1;
+ for (Description child : parameterizedFixtures) {
+ ArrayList<Description> tests = child.getChildren();
+ assertEquals(2, tests.size());
+ assertEquals("test1[" + i + "](" + className + ")", tests.get(0).getDisplayName());
+ assertEquals("test2[" + i + "](" + className + ")", tests.get(1).getDisplayName());
+ }
+ }
+}
Something went wrong with that request. Please try again.