Параллельное выполнение теста весной 5
1. Вступление
Начиная сJUnit 4, тесты можно запускать параллельно, чтобы увеличить скорость для более крупных пакетов. Проблема заключалась в том, что параллельное выполнение теста не полностью поддерживалосьSpring TestContext Framework доSpring 5.
В этой быстрой статье мы покажем, какuse Spring 5 to run our tests in Spring projects concurrently.
2. Maven Setup
Напоминаем, что для параллельного запуска тестовJUnit нам необходимо настроитьmaven-surefire-plugin, чтобы включить эту функцию:
org.apache.maven.plugins
maven-surefire-plugin
2.19.1
methods
true
Вы можете проверитьreference documentation для более подробной настройки параллельного выполнения теста.
3. Параллельный тест
Следующий пример теста завершится ошибкой при параллельной работе для версий доSpring 5.
Однако вSpring 5 он будет работать без сбоев:
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = Spring5JUnit4ConcurrentTest.SimpleConfiguration.class)
public class Spring5JUnit4ConcurrentTest implements ApplicationContextAware, InitializingBean {
@Configuration
public static class SimpleConfiguration {}
private ApplicationContext applicationContext;
private boolean beanInitialized = false;
@Override
public void afterPropertiesSet() throws Exception {
this.beanInitialized = true;
}
@Override
public void setApplicationContext(
final ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Test
public void whenTestStarted_thenContextSet() throws Exception {
TimeUnit.SECONDS.sleep(2);
assertNotNull(
"The application context should have been set due to ApplicationContextAware semantics.",
this.applicationContext);
}
@Test
public void whenTestStarted_thenBeanInitialized() throws Exception {
TimeUnit.SECONDS.sleep(2);
assertTrue(
"This test bean should have been initialized due to InitializingBean semantics.",
this.beanInitialized);
}
}
При последовательной работе вышеприведенные тесты могут пройти около 6 секунд. При параллельном выполнении это займет всего около 4,5 секунд - что довольно типично для того, сколько времени мы можем сэкономить и в больших наборах.
4. Под капотом
Основная причина, по которой предыдущие версии платформы не поддерживали одновременное выполнение тестов, была связана с управлениемTestContextTestContextManager.
ВSpring 5TestContextManager использует локальный поток -TestContext - чтобы гарантировать, что операции надTestContexts в каждом потоке не будут мешать друг другу. Таким образом, потокобезопасность гарантируется для большинства параллельных тестов уровня метода и класса:
public class TestContextManager {
// ...
private final TestContext testContext;
private final ThreadLocal testContextHolder = new ThreadLocal() {
protected TestContext initialValue() {
return copyTestContext(TestContextManager.this.testContext);
}
};
public final TestContext getTestContext() {
return this.testContextHolder.get();
}
// ...
}
Обратите внимание, что поддержка параллелизма не распространяется на все виды тестов; we need to exclude tests that:
-
изменять внешние общие состояния, такие как состояния в кэшах, базах данных, очередях сообщений и т. д.
-
требуют определенных порядков выполнения, например, тестов, использующихJUnit ’s@FixMethodOrder
-
изменитьApplicationContext, которые обычно обозначаются@DirtiesContext
5. Резюме
В этом кратком руководстве мы показали базовый пример использованияSpring 5 для параллельного запуска тестов.
Как всегда, пример кода можно найтиover on Github.