Ganchos de pepino

1. Introducción

Los anzuelos de pepino pueden ser útiles cuando queremos realizar acciones específicas para cada escenario o paso, pero sin tener estas acciones explícitamente en el código de Gherkin.

En este tutorial, veremos los ganchos @Before , @BeforeStep, @AfterStep y @After Cucumber.

2. Descripción general de los ganchos en pepino

2.1. ¿Cuándo deben usarse los ganchos?

Los enganches se pueden utilizar para realizar tareas en segundo plano que no forman parte de la funcionalidad empresarial. Tales tareas podrían ser:

  • Iniciar un navegador
  • Configurar o borrar cookies
  • Conectarse a una base de datos
  • Comprobando el estado del sistema
  • Supervisión

Un caso de uso para el monitoreo sería actualizar un tablero con el progreso de la prueba en tiempo real.

Los ganchos no son visibles en el código Gherkin. Por lo tanto, no deberíamos verlos como un reemplazo de un fondo de pepino o un paso dado .

Veremos un ejemplo en el que usamos ganchos para tomar capturas de pantalla durante la ejecución de la prueba.

2.2. Alcance de los ganchos

Los ganchos afectan a todos los escenarios. Por lo tanto, es una buena práctica definir todos los ganchos en una clase de configuración dedicada.

No es necesario definir los mismos ganchos en cada clase de código de pegamento. Si definimos ganchos en la misma clase con nuestro código de pegamento, tendríamos un código menos legible.

3. Ganchos

Primero veamos los ganchos individuales. Luego veremos un ejemplo completo en el que veremos cómo se ejecutan los ganchos cuando se combinan.

3.1. @Antes de

Los métodos anotados con @Before se ejecutarán antes de cada escenario . En nuestro ejemplo, iniciaremos el navegador antes de cada escenario:

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

Si anotamos varios métodos con @Before , podemos definir explícitamente el orden en el que se ejecutan los pasos:

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

El método anterior se ejecuta en segundo lugar, ya que pasamos 2 como valor para el parámetro de orden a la anotación. También podemos pasar 1 como valor para el parámetro de orden de nuestro método de inicialización:

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

Entonces, cuando ejecutamos un escenario, initialization () se ejecuta primero y beforeScenario () se ejecuta en segundo lugar.

3.2. @BeforeStep

Los métodos anotados con @BeforeStep se ejecutan antes de cada paso . Usemos la anotación para tomar una captura de pantalla antes de cada paso:

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

3.3. @AfterStep

Los métodos anotados con @AfterStep se ejecutan después de cada paso :

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

Hemos usado @AfterStep aquí para tomar una captura de pantalla después de cada paso. Esto sucede independientemente de si el paso finaliza correctamente o falla .

3.4. @Después

Los métodos anotados con @After se ejecutan después de cada escenario :

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

En nuestro ejemplo, tomaremos una captura de pantalla final y cerraremos el navegador. Esto sucede independientemente de si el escenario finaliza correctamente .

3.5. El parámetro del escenario

Los métodos anotados con una anotación de gancho pueden aceptar un parámetro de tipo Escenario :

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

El objeto de tipo Escenario contiene información sobre el escenario actual. Se incluyen el nombre del escenario, el número de pasos, los nombres de los pasos y el estado (aprobado o reprobado). Esto puede ser útil si queremos realizar diferentes acciones para pruebas pasadas y fallidas.

4. Ejecución del gancho

4.1. Flujo feliz

Veamos ahora qué sucede cuando ejecutamos un escenario de Pepino con los cuatro tipos de ganchos:

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

Al observar el resultado de una ejecución de prueba en IntelliJ IDE, podemos ver el orden de ejecución:

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.

Finalmente, vimos cómo podíamos definir ganchos con la notación lambda de Java 8.

Como de costumbre, el código fuente completo de este artículo está disponible en GitHub.