我有一个带有Maven和JUnit的Java应用程序用于测试,带有故障安全和万无一失的插件。
我有2000多个集成测试。为了加快测试运行速度,我使用故障保护jvmfork来并行运行我的测试。我有一些繁重的测试类,它们通常在我的测试执行结束时运行,这会减慢我的CI验证过程。filesafe runorder:balanced对我来说是一个很好的选择,但我不能使用它,因为jvmfork。重命名测试类或移动到另一个包并按字母顺序运行它不是一个选择。有什么建议可以让我在验证过程开始时运行我的慢测试类吗?
7条答案
按热度按时间nfzehxib1#
在 JUnit 5(从5.8.0版本开始)中,测试类也可以订购。
其他Junit内置类排序器实现:
有关设置配置参数的其他方法(在 junit-platform.properties 文件旁边),请参见JUnit 5用户指南。
您也可以提供自己的排序器。必须实现
ClassOrderer
接口:请注意,
@Nested
测试类不能按ClassOrderer
排序。请参阅JUnit 5文档和ClassOrderer API docs以了解更多信息。
yqkkidmi2#
我给了我找到的答案的组合一个尝试:
Running JUnit4 Test classes in specified order
Running JUnit Test in parallel on Suite Level
第二个答案是基于这个
github
项目的这些classes
,它在BSD-2许可下可用。我定义了几个测试类:
然后我定义了测试套件:
(FastRunningTest 2是第一个类的副本,具有调整后的输出)
当我执行
TopLevelSuite
时,我得到以下输出:TopLevelSuite-1-thread-1: long test - started FastRunningTest1-1-thread-4: frt1-test4 - done FastRunningTest1-1-thread-2: frt1-test2 - done FastRunningTest1-1-thread-1: frt1-test1 - done FastRunningTest1-1-thread-3: frt1-test3 - done FastRunningTest1-1-thread-5: frt1-test5 - done FastRunningTest1-1-thread-3: frt1-test6 - done FastRunningTest1-1-thread-1: frt1-test8 - done FastRunningTest1-1-thread-5: frt1-test7 - done FastRunningTest2-2-thread-1: frt2-test1 - done FastRunningTest2-2-thread-2: frt2-test2 - done FastRunningTest2-2-thread-5: frt2-test5 - done FastRunningTest2-2-thread-3: frt2-test3 - done FastRunningTest2-2-thread-4: frt2-test4 - done TopLevelSuite-1-thread-1: long test - done TopLevelSuite-1-thread-1: long test - started FastRunningTest2-2-thread-5: frt2-test8 - done FastRunningTest2-2-thread-2: frt2-test6 - done FastRunningTest2-2-thread-1: frt2-test7 - done TopLevelSuite-1-thread-1: long test - done
它基本上显示了
LongRunningTest
是与FastRunningTests
并行执行的。Concurrent
Annotation定义的用于并行执行的线程的默认值是5
,可以在FastRunningTests
的并行执行的输出中看到。缺点是这些
Threads
不在FastRunningTest1
和FastRunningTest2
之间共享。这种行为表明,它是“有点”可能做什么,你想做的(所以是否与您目前的设置是一个不同的问题)。
我也不确定这是否真的值得努力,
TestSuites
(或编写一些自动生成它们的东西)threads
)由于这基本上表明可以定义类的执行顺序并触发它们的并行执行,因此也可以让整个过程只使用一个
ThreadPool
(但我不确定这意味着什么)。由于整个概念是基于ThreadPoolExecutor,使用
PriorityBlockingQueue
,它为长时间运行的任务提供了更高的优先级,您将更接近于首先执行长时间运行的测试的理想结果。我做了更多的实验,实现了自己的自定义suite runner和junit runner。背后的想法是让你的JUnitRunner将测试提交到一个由单个
ThreadPoolExecutor
处理的队列中。因为我没有在RunnerScheduler#finish
方法中实现阻塞操作,所以我最终得到了一个解决方案,在这个解决方案中,所有类的测试都在执行开始之前传递到队列。(如果涉及更多的测试类和方法,这可能会有所不同)。至少它证明了一点,如果你真的想的话,你可以在这个级别上摆弄junit。
我的poc的代码有点乱,放在这里太长了,但是如果有人感兴趣,我可以把它推到github项目中。
3hvapo4f3#
junit5.8.0-M1版本中有一个解决方案。
基本上,你需要创建自己的排序器。我做过类似的事。
下面是一个注解,你将在测试类中使用它:
然后,您需要创建将实现org.junit.jupiter.API.ClassOrderer的类
为了让它工作,你需要告诉junit你将使用哪个类来对描述符进行排序。因此,您需要创建文件“junit-platform.properties”,它应该在resources文件夹中。在这个文件中,你只需要一行命令你的排序器类:
现在你可以像Order annotation一样使用你的orderer annotation,但是是在类级别上:
我希望这将帮助某人。
dced5bon4#
在我们的项目中,我们创建了一些标记接口(例如
)
并将其放入带有慢速测试的测试类中JUnit的@Category注解中。
之后,我们为Gradle创建了一些特殊的任务,以便按类别或按自定义顺序运行几个类别的测试:
这个解决方案由Gradle提供,但也许它对你有帮助。
gpnt7bae5#
让我先总结一下,然后再提出建议。
1.集成测试很慢。这很好,很自然。
我们从单元测试中得到了良好和快速的反馈。
在这一刻,我们确信我们没有问题,得到快速反馈。但我们仍然希望更快地运行集成测试。我建议以下解决方案:
1.改进实际测试。它们往往是无效的,可以大大加快速度。
1.在后台运行集成测试(即不要等待他们的真实的时间反馈)。
它们比单元测试慢得多是很自然的。
1.如果您需要更快地从其中一些测试中获得反馈,请将集成测试拆分到组中,并单独运行它们。
1.在不同的JVM中运行集成测试。而不是同一个JVM中的不同线程!
在这种情况下,您不关心线程安全,也不应该关心它。
1.在不同的机器上运行集成测试等等。
我参与了许多不同的项目(其中一些项目的CI构建运行了48小时),前3步就足够了(即使是疯狂的情况)。步骤#4很少需要良好的测试。步骤#5是针对特定的情况。
你会看到我的建议与过程有关,而不是与工具有关,因为问题就在过程中。
人们经常忽略根本原因,并试图调优工具(本例中为Maven)。他们得到了外观上的改进,但所创建的解决方案的维护成本很高。
e0uiprwp6#
这是另一种可能的方式,在某些情况下可能是有用的。
例如,如果我想让所有的UI测试(需要很长时间才能执行)在常规单元测试之后运行。
为此,可以创建一个单独的源集,然后在常规测试后运行它。
build.gradle.kts:
像在
src/test/java/...
中一样,在src/uiTest/java/...
目录中创建UI测试现在,如果您执行
check
Gradle任务(./gradlew check
)(这只是一个执行其他测试任务的任务),则UI测试将在常规单元测试之后执行。旁注:
./gradlew uiTest
任务来执行UI测试./gradlew test
任务来执行单元测试ou6hu8tu7#
您可以使用Junit 5中的注解来设置您希望使用的测试顺序:用途:
Junit 5用户指南:https://junit.org/junit5/docs/current/user-guide/#writing-tests-test-execution-order
升级到Junit5可以相当容易地完成,文章开头的链接上的文档包含了您可能需要的所有信息。