Skip to content

Commit

Permalink
Merge pull request #658 from pimterry/iterable-datapoints
Browse files Browse the repository at this point in the history
Added support for iterable datapoints
  • Loading branch information
David Saff committed Apr 2, 2013
2 parents 540fa75 + b4b2070 commit b4b1b31
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 10 deletions.
17 changes: 13 additions & 4 deletions src/main/java/org/junit/experimental/theories/DataPoints.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
import java.lang.annotation.Target;

/**
* Annotating an array-typed field or method with @DataPoints will cause
* the values in the array (or returned array) to be used as potential
* parameters for theories in that class, when run with the
* Annotating an array or iterable-typed field or method with @DataPoints
* will cause the values in the array or iterable given to be used as potential
* parameters for theories in that class when run with the
* {@link org.junit.experimental.theories.Theories Theories} runner.
* <p>
* DataPoints will only be considered as potential values for parameters for
Expand All @@ -27,6 +27,14 @@
* &#064;ParameterSuppliedBy} annotations) will use all DataPoints that are
* assignable to the parameter type as potential values, including named sets of
* DataPoints.
* <p>
* DataPoints methods whose array types aren't assignable from the target
* parameter type (and so can't possibly return relevant values) will not be
* called when generating values for that parameter. Iterable-typed datapoints
* methods must always be called though, as this information is not available
* here after generic type erasure, so expensive methods returning iterable
* datapoints are a bad idea.
*
* <pre>
* &#064;DataPoints
* public static String[] dataPoints = new String[] { ... };
Expand All @@ -48,8 +56,9 @@
* @see org.junit.experimental.theories.FromDataPoints
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({FIELD, METHOD})
@Target({ FIELD, METHOD })
public @interface DataPoints {
String[] value() default {};

Class<? extends Throwable>[] ignoredExceptions() default {};
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.junit.Assume;
Expand Down Expand Up @@ -76,9 +77,11 @@ private void addMultiPointMethods(ParameterSignature sig, List<PotentialAssignme
for (FrameworkMethod dataPointsMethod : getDataPointsMethods(sig)) {
Class<?> returnType = dataPointsMethod.getReturnType();

if (returnType.isArray() && sig.canPotentiallyAcceptType(returnType.getComponentType())) {
if ((returnType.isArray() && sig.canPotentiallyAcceptType(returnType.getComponentType())) ||
Iterable.class.isAssignableFrom(returnType)) {
try {
addArrayValues(sig, dataPointsMethod.getName(), list, dataPointsMethod.invokeExplosively(null));
addDataPointsValues(returnType, sig, dataPointsMethod.getName(), list,
dataPointsMethod.invokeExplosively(null));
} catch (Throwable throwable) {
DataPoints annotation = dataPointsMethod.getAnnotation(DataPoints.class);
if (annotation != null && isAssignableToAnyOf(annotation.ignoredExceptions(), throwable)) {
Expand All @@ -101,9 +104,10 @@ private void addSinglePointMethods(ParameterSignature sig, List<PotentialAssignm

private void addMultiPointFields(ParameterSignature sig, List<PotentialAssignment> list) {
for (final Field field : getDataPointsFields(sig)) {
addArrayValues(sig, field.getName(), list, getStaticFieldValue(field));
Class<?> type = field.getType();
addDataPointsValues(type, sig, field.getName(), list, getStaticFieldValue(field));
}
}
}

private void addSinglePointFields(ParameterSignature sig, List<PotentialAssignment> list) {
for (final Field field : getSingleDataPointFields(sig)) {
Expand All @@ -114,6 +118,16 @@ private void addSinglePointFields(ParameterSignature sig, List<PotentialAssignme
}
}
}

private void addDataPointsValues(Class<?> type, ParameterSignature sig, String name,
List<PotentialAssignment> list, Object value) {
if (type.isArray()) {
addArrayValues(sig, name, list, value);
}
else if (Iterable.class.isAssignableFrom(type)) {
addIterableValues(sig, name, list, (Iterable<?>) value);
}
}

private void addArrayValues(ParameterSignature sig, String name, List<PotentialAssignment> list, Object array) {
for (int i = 0; i < Array.getLength(array); i++) {
Expand All @@ -123,6 +137,18 @@ private void addArrayValues(ParameterSignature sig, String name, List<PotentialA
}
}
}

private void addIterableValues(ParameterSignature sig, String name, List<PotentialAssignment> list, Iterable<?> iterable) {
Iterator<?> iterator = iterable.iterator();
int i = 0;
while (iterator.hasNext()) {
Object value = iterator.next();
if (sig.canAcceptValue(value)) {
list.add(PotentialAssignment.forValue(name + "[" + i + "]", value));
}
i += 1;
}
}

private Object getStaticFieldValue(final Field field) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import static org.junit.Assert.assertThat;
import static org.junit.tests.experimental.theories.TheoryTestUtils.potentialAssignments;

import java.util.Arrays;
import java.util.List;

import org.junit.Rule;
Expand All @@ -23,7 +24,6 @@ public class AllMembersSupplierTest {
@Rule
public ExpectedException expected = ExpectedException.none();


public static class HasDataPointsArrayField {
@DataPoints
public static String[] list = new String[] { "qwe", "asd" };
Expand Down Expand Up @@ -153,4 +153,57 @@ private List<PotentialAssignment> allMemberValuesFor(Class<?> testClass,
testClass.getConstructor(constructorParameterTypes))
.get(0));
}
}

public static class HasDataPointsListField {
@DataPoints
public static List<String> list = Arrays.asList("one", "two");

@Theory
public void theory(String param) {
}
}

@Test
public void dataPointsCollectionFieldsShouldBeRecognized() throws Throwable {
List<PotentialAssignment> assignments = potentialAssignments(
HasDataPointsListField.class.getMethod("theory", String.class));

assertEquals(2, assignments.size());
}

public static class HasDataPointsListMethod {
@DataPoints
public static List<String> getList() {
return Arrays.asList("one", "two");
}

@Theory
public void theory(String param) {
}
}

@Test
public void dataPointsCollectionMethodShouldBeRecognized() throws Throwable {
List<PotentialAssignment> assignments = potentialAssignments(
HasDataPointsListMethod.class.getMethod("theory", String.class));

assertEquals(2, assignments.size());
}

public static class HasDataPointsListFieldWithOverlyGenericTypes {
@DataPoints
public static List<Object> list = Arrays.asList("string", new Object());

@Theory
public void theory(String param) {
}
}

@Test
public void dataPointsCollectionShouldBeRecognizedIgnoringStrangeTypes() throws Throwable {
List<PotentialAssignment> assignments = potentialAssignments(
HasDataPointsListFieldWithOverlyGenericTypes.class.getMethod("theory", String.class));

assertEquals(1, assignments.size());
}
}

0 comments on commit b4b1b31

Please sign in to comment.