One of the many excellent new features of JUnit 4 is parameterized tests. These are data-driven tests where a test case runs repeatedly against a collection of test data, as if each run were its own test case.
A standard example:
@RunWith(Parameterized.class) public class ExampleDataDrivenTest { public static final class Data { private final String name; public Data(final String name) { this.name = name; } @Override public String toString() { return name; } } private final List<Data> data; public ExampleDataDrivenTest(final Data datum1, final Data datum2) { System.out.println("ExampleDataDrivenTest"); this.data = asList(datum1, datum2); } @Test public void dumpData() { for (final Data datum : data) System.out.println("datum = " + datum); } @Parameters public static Collection<Data[]> data() { final Data[][] data = new Data[][]{ {new Data("apple"), new Data("core")}}; return asList(data); } }
This produces:
ExampleDataDrivenTest datum = apple datum = core
This works great for a fixed number of test data, but I want to test a variable number of data. The change is straight-forward once you recall that the varargs Java language feature is implemented as an array:
@RunWith(Parameterized.class) public class ExampleDataDrivenTest { public static final class Data { private final String name; public Data(final String name) { this.name = name; } @Override public String toString() { return name; } } private final List<Data> data; public ExampleDataDrivenTest(final Data... data) { System.out.println("ExampleDataDrivenTest"); this.data = asList(data); } @Test public void dumpData() { for (final Data datum : data) System.out.println("datum = " + datum); } @Parameters public static Collection<Data[][]> data() { final Data[][][] data = new Data[][][]{ {{new Data("apple"), new Data("core")}}}; return asList(data); } }
Reflect on the constructor and you see:
public ExampleDataDrivenTest(ExampleDataDrivenTest$Data[])
This makes the change more obvious.
I can now write my annotated parameters as:
@Parameters public static Collection<Data[][]> data() { final Data[][][] data = new Data[][][]{{{ /* no data */ }}, {{new Data("apple"), new Data("core")}}, {{new Data("baltimore")}}}; return asList(data); }
To produce:
ExampleDataDrivenTest ExampleDataDrivenTest datum = apple datum = core ExampleDataDrivenTest datum = baltimore