在 JUnit 5 测试方法中提供多个参数
Feed multiple parameters in JUnit 5 test method
我想为我的代码库提供 "polymorphic" 个测试用例。具体来说,将有 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
的帮助下强制设置自定义参数提供程序?
2020-10-07 通过 beatngu13 更新
自 v1.0.0 起,@CartesianProductTest
作为 JUnit Pioneer extension pack for JUnit 5. Find details at https://junit-pioneer.org/docs/cartesian-product
的一部分可用
JUnit 5 示例
开箱即用不受支持 -- 但在 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);
}
产生如下测试计划:
在您的示例中,您还可以考虑使用 property-based 测试框架,例如 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
你告诉引擎生成
可能参数值的笛卡尔积。事实上,如果数量
combinations <= 1000 jqwik 会单独使用笛卡尔产品。
根据您还可以考虑的不同 Graph 实现的数量
一种为每个实现使用具体子类的方法,以及
在接口(或抽象超类)中指定测试本身:
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 需要 single additional dependency。
我想为我的代码库提供 "polymorphic" 个测试用例。具体来说,将有 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
的帮助下强制设置自定义参数提供程序?
2020-10-07 通过 beatngu13 更新
自 v1.0.0 起,@CartesianProductTest
作为 JUnit Pioneer extension pack for JUnit 5. Find details at https://junit-pioneer.org/docs/cartesian-product
JUnit 5 示例
开箱即用不受支持 -- 但在 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);
}
产生如下测试计划:
在您的示例中,您还可以考虑使用 property-based 测试框架,例如 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
你告诉引擎生成
可能参数值的笛卡尔积。事实上,如果数量
combinations <= 1000 jqwik 会单独使用笛卡尔产品。
根据您还可以考虑的不同 Graph 实现的数量 一种为每个实现使用具体子类的方法,以及 在接口(或抽象超类)中指定测试本身:
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 需要 single additional dependency。