Skip to content

Commit

Permalink
Merge pull request junit-team#348 from stefanbirkner/iterable
Browse files Browse the repository at this point in the history
Use Iterable for the parameters of Parameterized (fixes junit-teamgh-104).
  • Loading branch information
dsaff committed Dec 31, 2011
2 parents a681b76 + 5475e12 commit 45eaab7
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 51 deletions.
82 changes: 46 additions & 36 deletions src/main/java/org/junit/runners/Parameterized.java
@@ -1,11 +1,12 @@
package org.junit.runners;

import static java.lang.String.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.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
Expand All @@ -15,7 +16,6 @@
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;
import org.junit.runners.model.TestClass;

/**
* <p>
Expand All @@ -30,10 +30,9 @@
* &#064;RunWith(Parameterized.class)
* public class FibonacciTest {
* &#064;Parameters
* public static List&lt;Object[]&gt; data() {
* return Arrays.asList(new Object[][] {
* { 0, 0 }, { 1, 1 }, { 2, 1 }, { 3, 2 }, { 4, 3 }, { 5, 5 }, { 6, 8 }
* });
* 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 } });
* }
*
* private int fInput;
Expand Down Expand Up @@ -72,30 +71,18 @@ private class TestClassRunnerForParameters extends
BlockJUnit4ClassRunner {
private final int fParameterSetNumber;

private final List<Object[]> fParameterList;
private final Object[] fParameters;

TestClassRunnerForParameters(Class<?> type,
List<Object[]> parameterList, int i) throws InitializationError {
TestClassRunnerForParameters(Class<?> type, Object[] parameters, int i)
throws InitializationError {
super(type);
fParameterList= parameterList;
fParameters= parameters;
fParameterSetNumber= i;
}

@Override
public Object createTest() throws Exception {
return getTestClass().getOnlyConstructor().newInstance(
computeParams());
}

private Object[] computeParams() throws Exception {
try {
return fParameterList.get(fParameterSetNumber);
} catch (ClassCastException e) {
throw new Exception(String.format(
"%s.%s() must return a Collection of arrays.",
getTestClass().getName(), getParametersMethod(
getTestClass()).getName()));
}
return getTestClass().getOnlyConstructor().newInstance(fParameters);
}

@Override
Expand Down Expand Up @@ -131,11 +118,9 @@ protected Annotation[] getRunnerAnnotations() {
* Only called reflectively. Do not use programmatically.
*/
public Parameterized(Class<?> klass) throws Throwable {
super(klass, Collections.<Runner>emptyList());
List<Object[]> parametersList= getParametersList(getTestClass());
for (int i= 0; i < parametersList.size(); i++)
runners.add(new TestClassRunnerForParameters(getTestClass().getJavaClass(),
parametersList, i));
super(klass, Collections.<Runner> emptyList());
Iterable<Object[]> allParameters= getAllParameters();
createRunnersForParameters(allParameters);
}

@Override
Expand All @@ -144,24 +129,49 @@ protected List<Runner> getChildren() {
}

@SuppressWarnings("unchecked")
private List<Object[]> getParametersList(TestClass klass)
private Iterable<Object[]> getAllParameters()
throws Throwable {
return (List<Object[]>) getParametersMethod(klass).invokeExplosively(
null);
Object parameters= getParametersMethod().invokeExplosively(null);
if (parameters instanceof Iterable)
return (Iterable<Object[]>) parameters;
else
throw parametersMethodReturnedWrongType();
}

private FrameworkMethod getParametersMethod(TestClass testClass)
private FrameworkMethod getParametersMethod()
throws Exception {
List<FrameworkMethod> methods= testClass
List<FrameworkMethod> methods= getTestClass()
.getAnnotatedMethods(Parameters.class);
for (FrameworkMethod each : methods) {
int modifiers= each.getMethod().getModifiers();
if (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))
if (each.isStatic() && each.isPublic())
return each;
}

throw new Exception("No public static parameters method on class "
+ testClass.getName());
+ getTestClass().getName());
}

private void createRunnersForParameters(Iterable<Object[]> allParameters)
throws InitializationError, Exception {
try {
int i= 0;
for (Object[] parametersOfSingleTest : allParameters) {
TestClassRunnerForParameters runner= new TestClassRunnerForParameters(
getTestClass().getJavaClass(), parametersOfSingleTest,
i);
runners.add(runner);
++i;
}
} catch (ClassCastException e) {
throw parametersMethodReturnedWrongType();
}
}

private Exception parametersMethodReturnedWrongType() throws Exception {
String className= getTestClass().getName();
String methodName= getParametersMethod().getName();
String message= format("%s.%s() must return an Iterable of arrays.",
className, methodName);
return new Exception(message);
}
}
Expand Up @@ -26,7 +26,7 @@ public class ParameterizedTestTest {
@RunWith(Parameterized.class)
static public class FibonacciTest {
@Parameters
public static Collection<Object[]> data() {
public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][] { { 0, 0 }, { 1, 1 }, { 2, 1 },
{ 3, 2 }, { 4, 3 }, { 5, 5 }, { 6, 8 } });
}
Expand Down Expand Up @@ -60,9 +60,9 @@ public void count() {
@Test
public void failuresNamedCorrectly() {
Result result= JUnitCore.runClasses(FibonacciTest.class);
assertEquals(String
.format("test[1](%s)", FibonacciTest.class.getName()), result
.getFailures().get(0).getTestHeader());
assertEquals(
String.format("test[1](%s)", FibonacciTest.class.getName()),
result.getFailures().get(0).getTestHeader());
}

@Test
Expand Down Expand Up @@ -141,7 +141,7 @@ public int test() {

@Parameters
public static Collection<Object[]> data() {
return Collections.singletonList(new Object[] {1});
return Collections.singletonList(new Object[] { 1 });
}
}

Expand Down Expand Up @@ -175,7 +175,7 @@ public void meaningfulFailureWhenParametersNotPublic() throws Exception {
@RunWith(Parameterized.class)
static public class WrongElementType {
@Parameters
public static Collection<String> data() {
public static Iterable<String> data() {
return Arrays.asList("a", "b", "c");
}

Expand All @@ -185,14 +185,31 @@ public void aTest() {
}

@Test
public void meaningfulFailureWhenParameterListsAreNotArrays() {
String expected= String.format(
"%s.data() must return a Collection of arrays.",
WrongElementType.class.getName());
assertThat(testResult(WrongElementType.class).toString(),
containsString(expected));
public void meaningfulFailureWhenParametersAreNotArrays() {
assertThat(
testResult(WrongElementType.class).toString(),
containsString("WrongElementType.data() must return an Iterable of arrays."));
}

@RunWith(Parameterized.class)
static public class ParametersNotIterable {
@Parameters
public static String data() {
return "foo";
}

@Test
public void aTest() {
}
}

@Test
public void meaningfulFailureWhenParametersAreNotAnIterable() {
assertThat(
testResult(ParametersNotIterable.class).toString(),
containsString("ParametersNotIterable.data() must return an Iterable of arrays."));
}

@RunWith(Parameterized.class)
static public class PrivateConstructor {
private PrivateConstructor(int x) {
Expand All @@ -208,8 +225,8 @@ public static Collection<Object[]> data() {
public void aTest() {
}
}
@Test(expected=InitializationError.class)

@Test(expected= InitializationError.class)
public void exceptionWhenPrivateConstructor() throws Throwable {
new Parameterized(PrivateConstructor.class);
}
Expand Down

0 comments on commit 45eaab7

Please sign in to comment.