【发布时间】:2014-03-29 22:04:08
【问题描述】:
我正在试验 Gradle 并行运行测试的能力。我发现的主要设置是Test 任务的maxParallelForks 属性。我希望该设置的行为类似于使用Executors.newFixedThreadPool 来执行测试。即,固定数量的线程(Gradle 中的进程)同时执行;每当一个线程完成工作时,池中就会激活一个新线程。
但是,Gradle 的行为以一种不太理想的方式根本不同。看起来 Gradle 将测试类划分为数量等于 maxParallelForks 的组,然后 Gradle 为每个组生成一个进程并让这些进程并行执行。这种策略的问题很明显:它不能根据测试类所需的时间动态调整执行。
例如,假设你有 5 个类,maxParallelForks 设置为 2。在这 5 个类中,有一个慢的,其余的都比较快。一个理想的策略是让一个进程执行慢的进程,而另一个进程执行快的进程。然而,Gradle 所做的是将慢速的与一两个快速的组合在一起,并产生两个进程来执行两组类,这肯定不如理想情况下的最佳。
这是一个简单的演示。
一堂慢课:
class DemoTest {
@Test
void one() {
Thread.sleep( 5000 )
println System.getProperty('org.gradle.test.worker') + ": " + new Date().format('HH:mm:ss')
assert 1 == 1
}
@Test
void two() {
Thread.sleep( 5000 )
println System.getProperty('org.gradle.test.worker') + ": " + new Date().format('HH:mm:ss')
assert 1 == 1
}
}
快速课程(DemoTest2-4,具有相同的课程主体):
class DemoTest2 {
@Test
void one() {
Thread.sleep( 1000 )
println System.getProperty('org.gradle.test.worker') + ": " + new Date().format('HH:mm:ss')
assert 1 == 1
}
@Test
void two() {
Thread.sleep( 1000 )
println System.getProperty('org.gradle.test.worker') + ": " + new Date().format('HH:mm:ss')
assert 1 == 1
}
}
所有的类都在包junit中,恰好和一个著名的测试框架同名:-)
这是一个可能的输出:
junit.DemoTest2 > one STANDARD_OUT
2: 14:54:00
junit.DemoTest2 > two STANDARD_OUT
2: 14:54:01
junit.DemoTest4 > one STANDARD_OUT
2: 14:54:02
junit.DemoTest4 > two STANDARD_OUT
2: 14:54:03
junit.DemoTest > one STANDARD_OUT
3: 14:54:04
junit.DemoTest > two STANDARD_OUT
3: 14:54:09
junit.DemoTest3 > one STANDARD_OUT
3: 14:54:10
junit.DemoTest3 > two STANDARD_OUT
3: 14:54:11
junit.DemoTest5 > one STANDARD_OUT
3: 14:54:12
junit.DemoTest5 > two STANDARD_OUT
3: 14:54:13
如您所见,慢速类DemoTest 与两个快速类组合在一起。总运行时间约为 13 秒,如果将快速课程组合在一起,则可能需要 10 秒。
那么,是否有任何直接的方法可以在 Gradle 中优化此行为,而无需借助自定义 JUnit 运行器?
非常感谢。
【问题讨论】: