Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Pull request #182 && #483: Adding Parameter annotation for field para…

…meters
  • Loading branch information...
commit cbf46b88c2937aece7018fa50ba4dbb133e03d06 1 parent 6a8215a
@jherault jherault authored
View
4 src/main/java/org/junit/runners/BlockJUnit4ClassRunner.java
@@ -169,7 +169,7 @@ protected void validateInstanceMethods(List<Throwable> errors) {
errors.add(new Exception("No runnable methods"));
}
- private void validateFields(List<Throwable> errors) {
+ protected void validateFields(List<Throwable> errors) {
RULE_VALIDATOR.validate(getTestClass(), errors);
}
@@ -417,4 +417,4 @@ private long getTimeout(Test annotation) {
return 0;
return annotation.timeout();
}
-}
+}
View
101 src/main/java/org/junit/runners/Parameterized.java
@@ -5,6 +5,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+import java.lang.reflect.Field;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
@@ -12,6 +13,7 @@
import org.junit.runner.Runner;
import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.model.FrameworkField;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;
@@ -73,6 +75,35 @@
* names like <code>[1: fib(3)=2]</code>. If you don't use the name parameter,
* then the current parameter index is used as name.
* </p>
+ *
+ * You can also write:
+ *
+ * <pre>
+ * &#064;RunWith(Parameterized.class)
+ * public class FibonacciTest {
+ * &#064;Parameters
+ * 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 } });
+ * }
+ * &#064;Parameter(0)
+ * public int fInput;
+ *
+ * &#064;Parameter(1)
+ * public int fExpected;
+ *
+ * &#064;Test
+ * public void test() {
+ * assertEquals(fExpected, Fibonacci.compute(fInput));
+ * }
+ * }
+ * </pre>
+ *
+ * <p>
+ * Each instance of <code>FibonacciTest</code> will be constructed with the default constructor
+ * and fields annotated by <code>&#064;Parameter</code> will be initialized
+ * with the data values in the <code>&#064;Parameters</code> method.
+ * </p>
* @since 4.0
*/
public class Parameterized extends Suite {
@@ -108,6 +139,26 @@
String name() default "{index}";
}
+ /**
+ * Annotation for fields of the test class which will be initialized by the
+ * method annotated by <code>Parameters</code><br/>
+ * By using directly this annotation, the test class constructor isn't needed.<br/>
+ * Index range must start at 0.
+ * Default value is 0.
+ */
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.FIELD)
+ public static @interface Parameter {
+ /**
+ * Method that returns the index of the parameter in the array
+ * returned by the method annoted by <code>Parameters</code>.<br/>
+ * Index range must start at 0.
+ * Default value is 0.
+ * @return the index of the parameter.
+ */
+ int value() default 0;
+ }
+
private class TestClassRunnerForParameters extends BlockJUnit4ClassRunner {
private final Object[] fParameters;
@@ -122,7 +173,26 @@
@Override
public Object createTest() throws Exception {
- return getTestClass().getOnlyConstructor().newInstance(fParameters);
+ Object testClassInstance = null;
+ List<FrameworkField> fields = getTestClass().getAnnotatedFields(Parameter.class);
+ if (!fields.isEmpty()) {
+ if (fields.size() != fParameters.length)
+ throw new Exception("Wrong number of parameters and @parameter fields. @parameter fields counted: "+fields.size()+", available parameters: "+fParameters.length+".");
+ testClassInstance = getTestClass().getJavaClass().newInstance();
+ for (FrameworkField f : fields) {
+ Field field = f.getField();
+ Parameter annot = field.getAnnotation(Parameter.class);
+ int index = annot.value();
+ try {
+ field.set(testClassInstance, fParameters[index]);
+ } catch(IllegalArgumentException iare) {
+ throw new Exception(getTestClass().getName() + ": Trying to set "+field.getName()+" with the value "+fParameters[index]+" that is not the right type ("+fParameters[index].getClass().getSimpleName()+" instead of "+field.getType().getSimpleName()+").", iare);
+ }
+ }
+ } else {
+ testClassInstance = getTestClass().getOnlyConstructor().newInstance(fParameters);
+ }
+ return testClassInstance;
}
@Override
@@ -138,6 +208,35 @@ protected String testName(FrameworkMethod method) {
@Override
protected void validateConstructor(List<Throwable> errors) {
validateOnlyOneConstructor(errors);
+ List<FrameworkField> annotatedFieldsByParameter = getTestClass().getAnnotatedFields(Parameter.class);
+ if (annotatedFieldsByParameter.size() > 0) {
+ validateZeroArgConstructor(errors);
+ }
+ }
+
+ @Override
+ protected void validateFields(List<Throwable> errors) {
+ super.validateFields(errors);
+ List<FrameworkField> annotatedFieldsByParameter = getTestClass().getAnnotatedFields(Parameter.class);
+ if (annotatedFieldsByParameter.size() > 0) {
+ int[] usedIndices = new int[annotatedFieldsByParameter.size()];
+ for (FrameworkField f : annotatedFieldsByParameter) {
+ int index = f.getField().getAnnotation(Parameter.class).value();
+ if (index < 0 || index > annotatedFieldsByParameter.size()-1) {
+ errors.add(new Exception("Invalid @parameter value: "+index+". @parameter fields counted: "+annotatedFieldsByParameter.size()+". Please use an index between 0 and "+(annotatedFieldsByParameter.size()-1)+"."));
+ } else {
+ usedIndices[index]++;
+ }
+ }
+ for (int index = 0 ; index < usedIndices.length ; index++) {
+ int numberOfUse = usedIndices[index];
+ if (numberOfUse == 0) {
+ errors.add(new Exception("The index "+index+" is never used."));
+ } else if (numberOfUse > 1) {
+ errors.add(new Exception("The index "+index+" is used more than once ("+numberOfUse+")."));
+ }
+ }
+ }
}
@Override
View
120 src/test/java/org/junit/tests/running/classes/ParameterizedTestTest.java
@@ -3,11 +3,13 @@
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
import static org.junit.experimental.results.PrintableResult.testResult;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.List;
import org.junit.AfterClass;
import org.junit.BeforeClass;
@@ -18,7 +20,9 @@
import org.junit.runner.Result;
import org.junit.runner.RunWith;
import org.junit.runner.Runner;
+import org.junit.runner.notification.Failure;
import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
import org.junit.runners.model.InitializationError;
@@ -102,6 +106,120 @@ public void usesIndexAsTestName() {
assertEquals("[1]", description.getChildren().get(1).getDisplayName());
}
+ @RunWith(Parameterized.class)
+ static public class FibonacciWithParameterizedFieldTest {
+ @Parameters
+ public static Collection<Object[]> data() {
+ return Arrays.asList(new Object[][] { { 0, 0 }, { 1, 1 }, { 2, 1 },
+ { 3, 2 }, { 4, 3 }, { 5, 5 }, { 6, 8 } });
+ }
+
+ @Parameter(0)
+ public int fInput;
+
+ @Parameter(1)
+ public int fExpected;
+
+ @Test
+ public void test() {
+ assertEquals(fExpected, fib(fInput));
+ }
+
+ private int fib(int x) {
+ return 0;
+ }
+ }
+
+ @Test
+ public void countWithParameterizedField() {
+ Result result= JUnitCore.runClasses(FibonacciWithParameterizedFieldTest.class);
+ assertEquals(7, result.getRunCount());
+ assertEquals(6, result.getFailureCount());
+ }
+
+ @Test
+ public void failuresNamedCorrectlyWithParameterizedField() {
+ Result result= JUnitCore.runClasses(FibonacciWithParameterizedFieldTest.class);
+ assertEquals(String
+ .format("test[1](%s)", FibonacciWithParameterizedFieldTest.class.getName()), result
+ .getFailures().get(0).getTestHeader());
+ }
+
+ @Test
+ public void countBeforeRunWithParameterizedField() throws Exception {
+ Runner runner= Request.aClass(FibonacciWithParameterizedFieldTest.class).getRunner();
+ assertEquals(7, runner.testCount());
+ }
+
+ @Test
+ public void plansNamedCorrectlyWithParameterizedField() throws Exception {
+ Runner runner= Request.aClass(FibonacciWithParameterizedFieldTest.class).getRunner();
+ Description description= runner.getDescription();
+ assertEquals("[0]", description.getChildren().get(0).getDisplayName());
+ }
+
+ @RunWith(Parameterized.class)
+ static public class BadIndexForAnnotedFieldTest {
+ @Parameters
+ public static Collection<Object[]> data() {
+ return Arrays.asList(new Object[][] { { 0 } });
+ }
+
+ @Parameter(2)
+ public int fInput;
+
+ public int fExpected;
+
+ @Test
+ public void test() {
+ assertEquals(fExpected, fib(fInput));
+ }
+
+ private int fib(int x) {
+ return 0;
+ }
+ }
+
+ @Test
+ public void failureOnInitialization() {
+ Result result = JUnitCore.runClasses(BadIndexForAnnotedFieldTest.class);
+ assertEquals(2, result.getFailureCount());
+ List<Failure> failures = result.getFailures();
+ assertEquals("Invalid @parameter value: 2. @parameter fields counted: 1. Please use an index between 0 and 0.",
+ failures.get(0).getException().getMessage());
+ assertEquals("The index 0 is never used.", failures.get(1).getException().getMessage());
+ }
+
+ @RunWith(Parameterized.class)
+ static public class BadNumberOfAnnotedFieldTest {
+ @Parameters
+ public static Collection<Object[]> data() {
+ return Arrays.asList(new Object[][] { { 0, 0 } });
+ }
+
+ @Parameter(0)
+ public int fInput;
+
+ public int fExpected;
+
+ @Test
+ public void test() {
+ assertEquals(fExpected, fib(fInput));
+ }
+
+ private int fib(int x) {
+ return 0;
+ }
+ }
+
+ @Test
+ public void numberOfFieldsAndParametersShouldMatch() {
+ Result result = JUnitCore.runClasses(BadNumberOfAnnotedFieldTest.class);
+ assertEquals(1, result.getFailureCount());
+ List<Failure> failures = result.getFailures();
+ assertTrue(failures.get(0).getException().getMessage().contains("Wrong number of parameters and @parameter fields. @parameter fields counted: 1, available parameters: 2."));
+ }
+
private static String fLog;
@RunWith(Parameterized.class)
@@ -254,4 +372,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.