I want to provide my codebase with "polymorphic" test cases. Specifically, there are going to be multiple implementations of a Graph
interface and would like to reuse the test code for all of them (ALGraph
, AMGraph
, ...).
I'd like to develop my test methods along the following lines
@ParameterizedTest
@MethodSource("graphFactory")
// Note: JUnit 5 won't allow the following additional argument source
@ValueSource(ints = {0, 31415, -31415})
void testInsertDeleteNode(Graph g, Integer v) {
g.insertNode(new Node<>(v));
assertTrue(g.containsNode(new Node<>(v)));
assertEquals(1, g.vertices().size());
g.deleteNode(new Node<>(v));
assertFalse(g.containsNode(new Node<>(v)));
assertEquals(0, g.vertices().size());
}
but the way JUnit is built is preventing me from accomplishing this scheme.
So basically I'd like to provide a cartesian product of multiple arguments to my tests. Is that possible with the out-of-the-box argument providers (ValueSource
, NullSource
, ...) or do I forcibly need to set up customized ones with the aid of @MethodSource
?
It's not supported out of the box -- but there already exists a feature request at https://github.com/junit-team/junit5/issues/1427
Find an example and proof of concept solution here: https://github.com/junit-team/junit5-samples/tree/master/junit5-jupiter-extensions
@CartesianProductTest({"0", "1"})
void threeBits(String a, String b, String c) {
int value = Integer.parseUnsignedInt(a + b + c, 2);
assertTrue((0b000 <= value) && (value <= 0b111));
}
@CartesianProductTest
@DisplayName("S ⨯ T ⨯ U")
void nFold(String string, Class<?> type, TimeUnit unit, TestInfo info) {
assertTrue(string.endsWith("a"));
assertTrue(type.isInterface());
assertTrue(unit.name().endsWith("S"));
assertTrue(info.getTags().isEmpty());
}
static CartesianProductTest.Sets nFold() {
return new CartesianProductTest.Sets()
.add("Alpha", "Omega")
.add(Runnable.class, Comparable.class, TestInfo.class)
.add(TimeUnit.DAYS, TimeUnit.HOURS);
}
Yields a test plan like: