欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

用置换破坏您的JUnit5测试

发布时间:2023/12/3 49 豆豆
生活随笔 收集整理的这篇文章主要介绍了 用置换破坏您的JUnit5测试 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

编写JUnit测试可能是一个乏味而乏味的过程。 了解如何使用排列结合TestFactory方法和DynamicTest对象以最少的编码工作来改进测试类。

在本文中,我将使用Java流ORM Speedment,因为它包含一个现成的Permutation类,从而帮助我节省了开发时间。 否则,加速可以将数据库表连接到标准Java流。 Speedment是一个开放源代码工具,也有免费版本供商业数据库使用。

测试流

考虑以下JUnit5测试:

@Test void test() {List<String> actual = Stream.of("CCC", "A", "BB", "BB").filter(string -> string.length() > 1).sorted().distinct().collect(toList());List<String> expected = Arrays.asList("BB", "CCC");assertEquals(actual, expected); }

如可以看到的,该测试将创建一个Stream与所述元素“CCC”,“A”,“B-B”和‘BB’,然后应用一个过滤器,将删除‘A’元素(因为它的长度是不大于1的)。 之后,对元素进行排序,以便流中具有元素“ BB”,“ BB”和“ CCC”。 然后,应用独特的操作,删除流中的所有重复项,在调用最终终止运算符之前保留元素“ BB”和“ CCC”,从而将这些其余元素收集到
List 。

经过一番考虑,可以理解,中间操作filter() , sorted()和distinct()的应用sorted()无关紧要。 因此,无论操作员应用程序的顺序如何,我们都期望得到相同的结果。

但是,我们如何才能找到一个JUnit5测试来证明该顺序对于所有排列都是无关紧要的,而无需手动为所有六个排列编写单独的测试用例?

使用TestFactory

除了编写单个测试,我们还可以使用TestFactory生成任意数量的DynamicTest对象。 这是演示该概念的简短示例:

@TestFactory Stream<DynamicTest> testDynamicTestStream() {return Stream.of(DynamicTest.dynamicTest("A", () -> assertEquals("A", "A")),DynamicTest.dynamicTest("B", () -> assertEquals("B", "B"))); }

这将产生两个可能毫无意义的名为“ A”和“ B”的测试。 请注意,我们如何方便地返回DynamicTest对象Stream ,而无需先将它们收集到
诸如List Collection 。

使用排列

Permutation类可用于创建任何类型T所有可能组合。 这是带有类型的简单示例
String :

Permutation.of("A", "B", "C").map(is -> is.collect(toList())).forEach(System.out::println);

因为Permutation创建了类型为T的Stream的Stream ,所以我们添加了一个中间映射操作,将内部Stream收集到List 。 上面的代码将产生以下输出:

[A, B, C] [A, C, B] [B, A, C] [B, C, A] [C, A, B] [C, B, A]

容易证明,这是将“ A”,“ B”和“ C”组合在一起的所有方式,每个要素应恰好发生一次。

创建运算符

在本文中,我选择为中间操作创建Java对象,而不是使用lambda,因为我想覆盖toString()方法并将其用于方法标识。 在其他情况下,直接使用lambda或方法引用就足够了:

UnaryOperator<Stream<String>> FILTER_OP = new UnaryOperator<Stream<String>>() {@Overridepublic Stream<String> apply(Stream<String> s) {return s.filter(string -> string.length() > 1);}@Overridepublic String toString() {return "filter";}};UnaryOperator<Stream<String>> DISTINCT_OP = new UnaryOperator<Stream<String>>() {@Overridepublic Stream<String> apply(Stream<String> s) {return s.distinct();}@Overridepublic String toString() {return "distinct";} };UnaryOperator<Stream<String>> SORTED_OP = new UnaryOperator<Stream<String>>() {@Overridepublic Stream<String> apply(Stream<String> s) {return s.sorted();}@Overridepublic String toString() {return "sorted";} };

测试排列

现在,我们可以轻松地在运算符上测试置换的工作方式:

void printAllPermutations() {Permutation.of(FILTER_OP,DISTINCT_OP,SORTED_OP).map(is -> is.collect(toList())).forEach(System.out::println); }

这将产生以下输出:

[filter, distinct, sorted] [filter, sorted, distinct] [distinct, filter, sorted] [distinct, sorted, filter] [sorted, filter, distinct] [sorted, distinct, filter]

可以看出,这些都是我们要测试的中间操作的置换。

拼接起来

通过结合以上学习,我们可以创建TestFactory ,以测试应用于初始流的中间操作的所有排列:

@TestFactory Stream<DynamicTest> testAllPermutations() {List<String> expected = Arrays.asList("BB", "CCC");return Permutation.of(FILTER_OP,DISTINCT_OP,SORTED_OP).map(is -> is.collect(toList())).map(l -> DynamicTest.dynamicTest(l.toString(),() -> {List<String> actual = l.stream().reduce(Stream.of("CCC", "A", "BB", "BB"),(s, oper) -> oper.apply(s),(a, b) -> a).collect(toList());assertEquals(expected, actual);})); }

请注意我们如何使用Stream::reduce方法将中间操作逐步应用于初始Stream.of("CCC", "A", "BB", "BB") 。 合路器lambda
(a, b) -> a只是一个虚拟对象,仅用于合并并行流(此处未使用)。

爆炸警告

最后,对置换的内在数学复杂性提出了警告。 根据定义,排列的复杂度为O(n!) ,例如,仅将一个元素添加到现有的八个元素的排列中,排列的数量将从40,320增加到362,880。

这是一把双刃剑。 我们几乎免费地获得了许多测试,但是我们必须付出在每个构建上执行每个测试的代价。

测试的源代码可以在这里找到。

可以在这里下载Speedment ORM

结论

Permutation , DynamicTest和TestFactory类是用于创建编程JUnit5测试的出色构建块。

注意不要在排列中使用太多元素。 “炸毁”可能意味着两件事……

翻译自: https://www.javacodegeeks.com/2018/10/blow-junit5-tests-permutations.html

总结

以上是生活随笔为你收集整理的用置换破坏您的JUnit5测试的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。