Следующий код должен соответствовать вашим требованиям, который был взят из немецкой книги JUnit Profiwissen , в которой содержатся некоторые советы либо для параллельного тестирования, либо для сокращения времени выполнения за счет использования нескольких ядер вместо толькоодноядерный.
JUnit 4.6 представил класс ParallelComputer, который предлагает параллельное выполнение тестов.Однако эта функциональность не была общедоступной до JUnit 4.7, который предоставлял возможность установить собственный планировщик для родительского бегуна.
public class ParallelScheduler implements RunnerScheduler {
private ExecutorService threadPool = Executors.newFixedThreadPool(
Runtime.getRuntime().availableProcessors());
@Override
public void schedule(Runnable childStatement) {
threadPool.submit(childStatement);
}
@Override
public void finished() {
try {
threadPool.shutdown();
threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("Got interrupted", e);
}
}
}
public class ParallelRunner extends BlockJUnit4ClassRunner {
public ParallelRunner(Class<?> klass) throws InitializationError {
super(klass);
setScheduler(new ParallelScheduler());
}
}
Если вы теперь аннотируете тестовый класс с помощью @RunWith(ParallelRunner.class)
, каждый метод будет запускатьсяв своей собственной теме.Кроме того, на исполняющем компьютере будет доступно столько активных потоков (только), сколько ядер ЦП.
Если несколько классов должны выполняться параллельно, вы можете определить специальный набор, например:
public class ParallelSuite extends Suite {
public ParallelSuite(Class<?> klass, RunnerBuilder builder)
throws InitializationError {
super(klass, builder);
setScheduler(new ParallelScheduler());
}
}
, а затем измените @RunWith(Suite.class)
на @RunWith(ParallelSuite.class)
Вы даже можете использовать функциональность, например, WildcardPatternSuite
, расширив его непосредственно из этого набора вместо Suite
, как в предыдущем примере.Это позволяет вам, кроме того, фильтровать юнит-тесты, например, по любому @Category
- TestSuite, который параллельно выполняет только UnitTest
аннотированные категории, может выглядеть так:
public interface UnitTest {
}
@RunWith(ParallelSuite.class)
@SuiteClasses("**/*Test.class")
@IncludeCategories(UnitTest.class)
public class UnitTestSuite {
}
Теперь простой тестовый пример может выглядеть следующим образомthis:
@Category(UnitTest.class)
@RunWith(MockitoJUnitRunner.class)
public class SomeClassTest {
@Test
public void testSomething() {
...
}
}
UnitTestSuite
выполнит каждый класс, найденный в подкаталогах, который заканчивается на Test
и имеет @Category(UnitTest.class)
, указанный параллельно - в зависимости от количества доступных ядер ЦП.
Я не уверен, может ли это быть проще:)