并发 JUnit 测试
我有一个大型 JUnit 测试套件,我很想同时运行所有测试,原因有两个:
- 利用多个内核更快地运行整个测试套件
- 希望检测到由于非线程安全全局对象而导致的一些错误
我认识到这一点这将迫使我重构一些代码以使其线程安全,但我认为这是一件好事:-)
让 JUnit 同时运行所有测试的最佳方法是什么?
I have a large JUnit test suite, where I'd quite like to run all the tests concurrently for two reasons:
- Exploit multiple cores to run the whole test suite faster
- Hopefully detect some errors due to non-thread-safe global objects
I recognise that this will force me to refactor some code to make it thread-safe, but I consider that to be a good thing :-)
What's the best way to get JUnit to run all the tests concurrently?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您固定使用 JUnit 了吗? TestNG 提供了良好的开箱即用的多线程测试,并且它与 JUnit 测试兼容(您需要进行一些更改)。例如,您可以运行这样的测试:
这意味着
doSomething()
方法将被 3 个不同的线程调用 9 次。我强烈推荐TestNG。
Are you fixed to JUnit? TestNG provides good multi thread testing out of the box and it's compatible with JUnit tests (you need to make a few changes). For example you could run a test like this:
This would mean that the
doSomething()
method will be invoked 9 times by 3 different threads.I highly recommend TestNG.
我一直在寻找这个问题的答案,根据这里的答案以及我在其他地方读到的内容,目前似乎没有一种简单的开箱即用的方法来使用并行运行现有测试JUnit。或者如果有的话我没找到。所以我写了一个简单的 JUnit Runner 来完成这个任务。请放心使用;请参阅http://falutin.net/2012/12/30/multithreaded-testing-with- junit/ 以获得完整的解释和 MultiThreadedRunner 类的源代码。使用此类,您可以像这样注释现有的测试类:
I was looking for an answer to exactly this question, and based on the answers here, and what I read elsewhere, it appears as if there isn't currently an easy out-of-the-box way to run existing tests in parallel using JUnit. Or if there is I didn't find it. So I wrote a simple JUnit Runner that accomplishes that. Please feel free to use it; see http://falutin.net/2012/12/30/multithreaded-testing-with-junit/ for a complete explanation and the source code of the MultiThreadedRunner class. With this class, you can just annotate your existing test class(es) like this:
以下代码应满足您的要求,该代码取自德语书籍 JUnit Profiwissen 其中包含一些关于并行测试内容或如何通过使用多核减少执行时间的提示而不是只有一个核心。
JUnit 4.6 引入了一个 ParallelComputer 类,它提供测试的并行执行。然而,直到 JUnit 4.7 才提供了为父运行器设置自定义调度程序的可能性,此功能才可公开访问。
如果您现在使用
@RunWith(ParallelRunner.class)
注释测试类,每个方法都将在其自己的线程中运行。此外,活动线程的数量(仅)与执行机器上可用的 CPU 核心数量一样多。如果要并行执行多个类,您可以像这样定义自定义套件:
然后将
@RunWith(Suite.class)
更改为@RunWith(ParallelSuite.class)
您甚至可以通过直接从该套件(而不是前面示例中的
Suite
)扩展来利用WildcardPatternSuite
的功能。这使您能够进一步通过任何@Category
过滤单元测试 - 一个仅并行执行UnitTest
带注释的类别的 TestSuite 可能如下所示:一个简单的测试用例现在可以如下所示:
UnitTestSuite
将执行在以Test
结尾的子目录中找到的每个类,并且在以下位置指定了@Category(UnitTest.class)
并行 - 取决于可用 CPU 核心的数量。我不确定它是否可以变得比这更简单:)
The following code should achieve your requirements which was taken from the German book JUnit Profiwissen which contains some hints to either tests stuff in parallel or on how to reduce execution time through using multiple cores instead of only a single core.
JUnit 4.6 introduced a ParallelComputer class which offered the parallel execution of tests. However, this functionality was not publicly accessible until JUnit 4.7 which provided the possibility to set a custom scheduler for the parent runner.
If you now annotate a test-class with
@RunWith(ParallelRunner.class)
each method will run within its own thread. Furthermore, there will be as many active threads (only) as CPU-cores are available at the executing machine.If multiple classes should be executed in parallel you can define a customized suite like this:
and then change
@RunWith(Suite.class)
with@RunWith(ParallelSuite.class)
You can even leverage the functionality of f.e. the
WildcardPatternSuite
by extending directly from that suite instead ofSuite
as in the example before. This enables you furthermore to filter unit-tests f.e. by any@Category
- a TestSuite which only executesUnitTest
annotated categories in parallel could look like this:A simple test case could now look like this:
The
UnitTestSuite
will execute each class found in subdirecotries that ends withTest
and has a@Category(UnitTest.class)
specified in parallel - depending on the number of CPU cores available.I'm not sure if it can get simpler than that :)
显然,Mathieu Carbou 在他的文章“Concurrent JUnit Tests With RunnerScheduler”中已经完成了并发的实现,这可能会有所帮助!
http://dzone.com/articles/concurrent-junit-tests
OneJunit
多个 JUnit :
Apparently in his post "Concurrent JUnit Tests With RunnerScheduler" Mathieu Carbou has done implementation for concurrence that could helps!
http://dzone.com/articles/concurrent-junit-tests
OneJunit
Multiple JUnits:
您还可以尝试 HavaRunner。它是一个 JUnit 运行器,默认情况下并行运行测试。
HavaRunner 还有方便的套件:您可以通过将注释
@PartOf(YourIntegrationTestSuite.class)
添加到类上来将测试声明为套件的成员。此方法与 JUnit 不同,在 JUnit 中,您在套件类中声明套件成员资格。此外,HavaRunner 套件还可以初始化重量级对象,例如嵌入式 Web 应用程序容器。然后,HavaRunner 将这个重量级对象传递给每个套件成员的构造函数。这消除了对 @BeforeClass 和 @AfterClass 注释的需要,这些注释是有问题的,因为它们促进全局可变状态,这反过来又使并行化变得困难。
最后,HavaRunner 有场景——一种针对不同数据运行相同测试的方法。场景减少了重复测试代码的需要。
HavaRunner 已经在两个中型 Java 项目中经过了实际测试。
诗。我是 HavaRunner 的作者,非常感谢您的反馈。
You can also try HavaRunner. It is a JUnit runner that runs tests in parallel by default.
HavaRunner also has handy suites: you can declare a test to be a member of a suite by adding the annotation
@PartOf(YourIntegrationTestSuite.class)
onto the class. This approach differs from JUnit's, where you declare the suite memberships in the suite class.In addition, HavaRunner suites may intialise heavy-weight objects such as an embedded web application container. HavaRunner then passes this heavy-weight object to the constructor of each suite member. This removes the need for the
@BeforeClass
and@AfterClass
annotations, which are problematic, because they promote global mutable state, which in turn makes parallelisation difficult.Lastly, HavaRunner has scenarios – a way to run the same test against different data. Scenarios reduce the need to duplicate test code.
HavaRunner has been battle-tested in two mid-size Java projects.
Ps. I'm the author of HavaRunner, and I'd appreciate your feedback on it.