Running JUnit Test in parallel on Suite Level?(在套件级别上并行运行 JUnit 测试?)
问题描述
我有一堆在 JUnit 测试套件中组织的测试.这些测试极大地利用 selenium 来测试 Web 应用程序.因此,对于 selenium,这些测试的运行时间很长.由于测试数据库中有一些重叠,套件中的测试类无法并行运行,我想并行运行这些套件.
I have a bunch of tests that are organized in JUnit test suites. These tests are greatly utilizing selenium to test a web application. So, naturaly for selenium, the runtime of these tests is quite long. Since the test classes in the suites can not run parallel due some overlaps in the test database, i would like to run the suites parallel.
JUnit ParallelComputer 只能在类或方法级别并行执行测试,JUnit 是否有任何标准方法可以通过套件执行此操作?
The JUnit ParallelComputer can only execute tests on class or method level in parallel, are there any standard ways for JUnit to do that with suites?
如果我只是将套件类传递给 junit 运行器并将计算机配置为在类级别并行化,它会选择测试类本身,而不是套件.
If i just pass suite classes to the junit runner and configure the computer to parallelize on class level, it picks the test classes itself, not the suites.
br弗兰克
推荐答案
这里有一些对我有用的代码.我没有写这个.如果您使用 @RunWith(ConcurrentSuite.class)
而不是 @RunWith(Suite.class)
它应该可以工作.下面还需要一个注释.
Here is some code that worked for me. I did not write this. If you use @RunWith(ConcurrentSuite.class)
instead of @RunWith(Suite.class)
it should work. There is an annotation that is also needed which is found below.
package utilities.runners;
import org.junit.internal.builders.AllDefaultPossibilitiesBuilder;
import org.junit.runner.Runner;
import org.junit.runners.Suite;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.RunnerBuilder;
import org.junit.runners.model.RunnerScheduler;
import utilities.annotations.Concurrent;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author Mathieu Carbou (mathieu.carbou@gmail.com)
*/
public final class ConcurrentSuite extends Suite {
public ConcurrentSuite(final Class<?> klass) throws InitializationError {
super(klass, new AllDefaultPossibilitiesBuilder(true) {
@Override
public Runner runnerForClass(Class<?> testClass) throws Throwable {
List<RunnerBuilder> builders = Arrays.asList(
new RunnerBuilder() {
@Override
public Runner runnerForClass(Class<?> testClass) throws Throwable {
Concurrent annotation = testClass.getAnnotation(Concurrent.class);
if (annotation != null)
return new ConcurrentJunitRunner(testClass);
return null;
}
},
ignoredBuilder(),
annotatedBuilder(),
suiteMethodBuilder(),
junit3Builder(),
junit4Builder());
for (RunnerBuilder each : builders) {
Runner runner = each.safeRunnerForClass(testClass);
if (runner != null)
return runner;
}
return null;
}
});
setScheduler(new RunnerScheduler() {
ExecutorService executorService = Executors.newFixedThreadPool(
klass.isAnnotationPresent(Concurrent.class) ?
klass.getAnnotation(Concurrent.class).threads() :
(int) (Runtime.getRuntime().availableProcessors() * 1.5),
new NamedThreadFactory(klass.getSimpleName()));
CompletionService<Void> completionService = new ExecutorCompletionService<Void>(executorService);
Queue<Future<Void>> tasks = new LinkedList<Future<Void>>();
@Override
public void schedule(Runnable childStatement) {
tasks.offer(completionService.submit(childStatement, null));
}
@Override
public void finished() {
try {
while (!tasks.isEmpty())
tasks.remove(completionService.take());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
while (!tasks.isEmpty())
tasks.poll().cancel(true);
executorService.shutdownNow();
}
}
});
}
static final class NamedThreadFactory implements ThreadFactory {
static final AtomicInteger poolNumber = new AtomicInteger(1);
final AtomicInteger threadNumber = new AtomicInteger(1);
final ThreadGroup group;
NamedThreadFactory(String poolName) {
group = new ThreadGroup(poolName + "-" + poolNumber.getAndIncrement());
}
@Override
public Thread newThread(Runnable r) {
return new Thread(group, r, group.getName() + "-thread-" + threadNumber.getAndIncrement(), 0);
}
}
}
并且注解如下.
package utilities.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Mathieu Carbou (mathieu.carbou@gmail.com)
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE })
public @interface Concurrent {
int threads() default 5;
}
这篇关于在套件级别上并行运行 JUnit 测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:在套件级别上并行运行 JUnit 测试?


- C++ 和 Java 进程之间的共享内存 2022-01-01
- 从 finally 块返回时 Java 的奇怪行为 2022-01-01
- Jersey REST 客户端:发布多部分数据 2022-01-01
- Java包名称中单词分隔符的约定是什么? 2022-01-01
- 如何使用WebFilter实现授权头检查 2022-01-01
- Spring Boot连接到使用仲裁器运行的MongoDB副本集 2022-01-01
- Safepoint+stats 日志,输出 JDK12 中没有 vmop 操作 2022-01-01
- Eclipse 插件更新错误日志在哪里? 2022-01-01
- value & 是什么意思?0xff 在 Java 中做什么? 2022-01-01
- 将log4j 1.2配置转换为log4j 2配置 2022-01-01