我想提供我的代码库与“多态”的测试案例。 具体来说,有将是一个多种实现Graph
界面,并想重新使用他们所有的测试代码( ALGraph
, AMGraph
,...)。
我想开发大意如下我的测试方法
@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());
}
但JUnit是构建方式阻止我完成这个计划。
所以基本上我想提供的多个参数笛卡尔积到我的测试。 这有可能与出的现成的说法提供商( ValueSource
, NullSource
,...)或者我强行要设置自定义那些与援助@MethodSource
?
它不支持开箱即用-但已经在存在功能请求https://github.com/junit-team/junit5/issues/1427
在这里找到的概念解决方案的例子, 证明 : 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);
}
产生一个测试计划,如:
在您的例子,还可以考虑使用像一个基于属性的测试框架jqwik 。 第一种方式使用它是非常相似的例子:
import net.jqwik.api.*;
import static org.junit.jupiter.api.Assertions.*;
@Property(generation = GenerationMode.EXHAUSTIVE)
void testInsertDeleteNode(
@ForAll("graphFactory") Graph g,
@ForAll("ints") 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());
}
@Provide
Arbitrary<Graph> graphFactory() {
return Arbitraries.of(new ALGraph(), new AMGraph());
}
@Provide
Arbitrary<Integer> ints() {
return Arbitraries.of(0, 31415, -31415);
}
通过使用generation = GenerationMode.EXHAUSTIVE
你告诉引擎产生可能的参数值的笛卡尔乘积。 事实上,如果组合的数目是<= 1000 jqwik会去的笛卡尔乘积所有的本身。
根据differen图执行的数目,你也可以考虑使用具体的子类每个实现的方法,并在指定的接口测试本身(或抽象超):
interface GraphTest<G extends Graph> {
G createGraph();
@Property(generation = GenerationMode.EXHAUSTIVE)
default void testInsertDeleteNode(@ForAll("ints") Integer v) {
Graph g = createGraph();
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());
}
@Provide
default Arbitrary<Integer> ints() {
return Arbitraries.of(0, 31415, -31415);
}
}
class ALGraphTest implements GraphTest<ALGraph> {
@Override
public ALGraph createGraph() {
return new ALGraph();
}
}
class AMGraphTest implements GraphTest<AMGraph> {
@Override
public AMGraph createGraph() {
return new AMGraph();
}
}
既然你已经使用JUnit 5平台,采用jqwik需要一个单独的附加依赖 。