Exécution simultanée de tests au printemps 5

Exécution simultanée des tests au printemps 5

1. introduction

À partir deJUnit 4, les tests peuvent être exécutés en parallèle pour gagner en vitesse pour les grandes suites. Le problème était que l'exécution de tests simultanés n'était pas entièrement prise en charge par lesSpring TestContext Framework avantSpring 5.

Dans cet article rapide, nous allons montrer commentuse Spring 5 to run our tests in Spring projects concurrently.

2. Maven Setup

Pour rappel, pour exécuter les testsJUnit en parallèle, nous devons configurer lesmaven-surefire-plugin pour activer la fonctionnalité:


    
        org.apache.maven.plugins
        maven-surefire-plugin
        2.19.1
        
            methods
            true
        
    

Vous pouvez consulter lesreference documentation pour une configuration plus détaillée sur l'exécution des tests en parallèle.

3. Test simultané

L'exemple de test suivant échouait lors de l'exécution en parallèle pour les versions antérieures àSpring 5.

Cependant, il fonctionnera correctement dansSpring 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);
    }
}

En cas d'exécution séquentielle, les tests ci-dessus prennent environ 6 secondes. Avec une exécution simultanée, cela ne prend que 4,5 secondes environ, ce qui est assez typique du temps que nous pouvons espérer économiser également dans des suites plus grandes.

4. Sous la capuche

La principale raison pour laquelle les versions précédentes du framework ne prenaient pas en charge l'exécution simultanée de tests était due à la gestion deTestContext par lesTestContextManager.

DansSpring 5, leTestContextManager utilise un thread local -TestContext - pour s'assurer que les opérations surTestContexts dans chaque thread n'interféreraient pas les unes avec les autres. Ainsi, la sécurité des threads est garantie pour la plupart des tests concurrents de niveaux méthode et classe:

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();
    }

    // ...
}

Notez que la prise en charge de la concurrence ne s'applique pas à tous les types de tests; we need to exclude tests that:

  • changer les états partagés externes, tels que les états dans les caches, les bases de données, les files de messages, etc.

  • nécessitent des ordres d'exécution spécifiques, par exemple, des tests utilisantJUnit´s@FixMethodOrder

  • modifier lesApplicationContext, qui sont généralement marqués par@DirtiesContext

5. Sommaire

Dans ce rapide tutoriel, nous avons montré un exemple de base utilisantSpring 5 pour exécuter des tests en parallèle.

Comme toujours, l'exemple de code peut être trouvéover on Github.