Crochets de concombre

1. Introduction

Les crochets de concombre peuvent être utiles lorsque nous voulons effectuer des actions spécifiques pour chaque scénario ou étape, mais sans avoir ces actions explicitement dans le code Gherkin.

Dans ce didacticiel, nous examinerons les crochets @Before , @BeforeStep, @AfterStep et @After Cucumber.

2. Présentation des crochets dans le concombre

2.1. Quand faut-il utiliser les crochets?

Les hooks peuvent être utilisés pour effectuer des tâches d'arrière-plan qui ne font pas partie des fonctionnalités métier. Ces tâches pourraient être:

  • Démarrer un navigateur
  • Définition ou suppression des cookies
  • Connexion à une base de données
  • Vérification de l'état du système
  • surveillance

Un cas d'utilisation pour la surveillance serait de mettre à jour un tableau de bord avec la progression du test en temps réel.

Les hooks ne sont pas visibles dans le code Gherkin. Par conséquent, nous ne devrions pas les voir comme un remplacement pour un fond de concombre ou une étape donnée .

Nous allons regarder un exemple où nous utilisons des hooks pour prendre des captures d'écran pendant l'exécution du test.

2.2. Portée des crochets

Les crochets affectent chaque scénario. Par conséquent, il est recommandé de définir tous les hooks dans une classe de configuration dédiée.

Il n'est pas nécessaire de définir les mêmes hooks dans chaque classe de code glue. Si nous définissons des hooks dans la même classe avec notre code glue, nous aurions un code moins lisible.

3. Crochets

Regardons d'abord les crochets individuels. Nous examinerons ensuite un exemple complet où nous verrons comment les hooks s'exécutent lorsqu'ils sont combinés.

3.1. @Avant

Méthodes annotés avec @Before seront exécuter avant chaque scénario . Dans notre exemple, nous allons démarrer le navigateur avant chaque scénario:

@Before public void initialization() { startBrowser(); }

Si nous annotons plusieurs méthodes avec @Before , nous pouvons définir explicitement l'ordre dans lequel les étapes sont exécutées:

@Before(order=2) public void beforeScenario() { takeScreenshot(); }

La méthode ci-dessus s'exécute en second, lorsque nous transmettons 2 comme valeur du paramètre de commande à l'annotation. Nous pouvons également passer 1 comme valeur pour le paramètre de commande de notre méthode d'initialisation:

@Before(order=1) public void initialization()

Ainsi, lorsque nous exécutons un scénario, initialization () s'exécute en premier et beforeScenario () s'exécute en second.

3.2. @BeforeStep

Les méthodes annotées avec @BeforeStep s'exécutent avant chaque étape . Utilisons l'annotation pour prendre une capture d'écran avant chaque étape:

@BeforeStep public void beforeStep() { takeScreenshot(); }

3.3. @AfterStep

Les méthodes annotées avec @AfterStep s'exécutent après chaque étape :

@AfterStep public void afterStep() { takeScreenshot(); }

Nous avons utilisé @AfterStep ici pour prendre une capture d'écran après chaque étape. Cela se produit indépendamment du fait que l'étape se termine avec succès ou échoue .

3.4. @Après

Les méthodes annotées avec @After s'exécutent après chaque scénario :

@After public void afterScenario() { takeScreenshot(); closeBrowser(); }

Dans notre exemple, nous prendrons une dernière capture d'écran et fermerons le navigateur. Cela se produit indépendamment du fait que le scénario se termine avec succès .

3.5. Le paramètre de scénario

Les méthodes annotées avec une annotation hook peuvent accepter un paramètre de type Scenario :

@After public void beforeScenario(Scenario scenario) { // some code }

L'objet de type Scénario contient des informations sur le scénario en cours. Le nom du scénario, le nombre d'étapes, les noms des étapes et l'état (réussite ou échec) sont inclus. Cela peut être utile si nous voulons effectuer différentes actions pour les tests réussis et échoués.

4. Exécution du crochet

4.1. Flux heureux

Voyons maintenant ce qui se passe lorsque nous exécutons un scénario de concombre avec les quatre types de crochets:

Feature: Book Store With Hooks Background: The Book Store Given The following books are available in the store | The Devil in the White City | Erik Larson | | The Lion, the Witch and the Wardrobe | C.S. Lewis | | In the Garden of Beasts | Erik Larson | Scenario: 1 - Find books by author When I ask for a book by the author Erik Larson Then The salesperson says that there are 2 books Scenario: 2 - Find books by author, but isn't there When I ask for a book by the author Marcel Proust Then The salesperson says that there are 0 books

En regardant le résultat d'un test exécuté dans IntelliJ IDE, nous pouvons voir l'ordre d'exécution:

First, our two @Before hooks execute. Then before and after every step, the @BeforeStep and @AfterStep hooks run, respectively. Finally, the @After hook runs. All hooks execute for both scenarios.

4.2. Unhappy Flow: a Step Fails

Let's see what happens if a step fails. As we can see in the screenshot below, both the @Before and @After hooks of the failing step are executed. The subsequent steps are skipped, and finally, the @After hook executes:

The behavior of @After is similar to the finally-clause after a try-catch in Java. We could use it to perform clean-up tasks if a step failed. In our example, we still take a screenshot even if the scenario fails.

4.3. Unhappy Flow: a Hook Fails

Let's look at what happens when a hook itself fails. In the example below, the first @BeforeStep fails.

In this case, the actual step doesn't run, but it's @AfterStep hook does. Subsequent steps won't run either, whereas the @After hook is executed at the end:

5. Conditional Execution with Tags

Hooks are defined globally and affect all scenarios and steps. However, with the help of Cucumber tags, we can define exactly which scenarios a hook should be executed for:

@Before(order=2, value="@Screenshots") public void beforeScenario() { takeScreenshot(); }

This hook will be executed only for scenarios that are tagged with @Screenshots:

@Screenshots Scenario: 1 - Find books by author When I ask for a book by the author Erik Larson Then The salesperson says that there are 2 books

6. Java 8

We can add Cucumber Java 8 Support to define all hooks with lambda expressions.

Recall our initialization hook from the example above:

@Before(order=2) public void initialization() { startBrowser(); }

Rewritten with a lambda expression, we get:

public BookStoreWithHooksRunSteps() { Before(2, () -> startBrowser()); }

The same also works for @BeforeStep, @After, and @AfterStep.

7. Conclusion

In this article, we looked at how to define Cucumber hooks.

We discussed in which cases we should use them and when we should not. Then, we saw in which order hooks execute and how we can achieve conditional execution.

Enfin, nous avons vu comment nous pourrions définir des hooks avec la notation lambda Java 8.

Comme d'habitude, le code source complet de cet article est disponible à l'adresse over sur GitHub.