BDDevelopment en Javascript con Cucumber

Hasta ahora hemos revisado el Desarrollo Guiado por Pruebas (TDD: Test Driven Development) y los beneficios que este aporta a nuestras aplicaciones, así como el impacto que tiene en el ciclo de vida de desarrollo. Cada vez que escribimos una prueba para un trozo de código, comprobamos que el código funciona. Y, lo que es más importante, sabremos en el futuro si ese código se rompe.

El Desarrollo Guiado por Comportamiento (BDD: Behavior Driven Development) es una extensión de este concepto, pero en lugar de probar el código, estamos probando la aplicación, y específicamente que la aplicación se comporta como se requiere.

En este artículo veremos cómo podemos implementar las pruebas BDD en un proyecto JavaScript, utilizando el framework Cucumber.js .

Una de las diferencias importantes a la hora de especificar pruebas TDD y BDD es el público objetivo dentro del proyecto:

En el caso TDD, los desarrolladores escriben, mantienen y entienden las pruebas que escribieron para el código que están probando. Es muy posible que nadie más necesite leer las pruebas.

En el caso BDD, las pruebas deben ser entendidas por un público mucho más amplio. Hay muchas más partes implicadas en que la aplicación se comporte como debería: personal de control de calidad, analistas de aplicaciones, ventas, incluso la alta gerencia.

Esto significa que las pruebas BDD deben redactarse de forma que cualquier persona que comprenda el producto pueda coger las pruebas y comprenderlas también.

Por ello es deseable que los test BDD se escriban en un lenguaje que sea human-friendly y esto es Gherkin.

Gherkin es un Lenguaje de Dominio Específico (DSL: Domain Specific Language) que se utiliza para escribir pruebas BDD y específicamente las pruebas Cucumber. Permite que los scripts de prueba se escriban en un formato legible por humanos, que luego se puede compartir entre todos los implicados en el desarrollo del producto.

Los archivos Gherkin son archivos que contienen pruebas escritas en el lenguaje Gherkin. Estos archivos suelen tener una extensión de archivo .feature.

El contenido de los archivos Gherkin

En una prueba definida en Gherkin, se trabaja con dos conceptos: características y escenarios.

Un escenario es, literalmente, una sola prueba, que debe probar exactamente una cosa en la aplicación.

Una característica es un grupo de escenarios relacionados. En una característica se probarán muchos aspectos relacionadas dentro de la aplicación.

Lo ideal es que las características Gherkin se correlacionen estrechamente con las características de la aplicación, de ahí el nombre.

Cada archivo Gherkin contiene exactamente una característica, y cada característica contiene uno o más escenarios.

Los escenarios están compuestos por pasos (steps), que se ordenan de una manera específica:

  • Given (Dado): este paso se usa para configurar el estado inicial antes de realizar la prueba
  • When (Cuándo): este paso es la prueba real que se debe ejecutar
  • Then (Entonces): este paso se usa para hacer una afirmación sobre el resultado de la prueba

Idealmente, cada escenario debe ser un caso de prueba único, por lo que el número de pasos se mantendrá muy pequeño.

Los pasos son opcionales. Por ejemplo, si no se necesita configurar nada, es posible que no se tenga el paso given.

Los archivos Gherkin están diseñados para ser legibles por humanos y por tanto, que cualquier persona involucrada en el desarrollo del producto pueda examinarlos y entenderlos. Como esto incluye personas no técnicas, los archivos Gherkin siempre deben estar escritos en lenguaje comercial y no técnico. Esto a su vez significa, por ejemplo, que no se hará referencia a componentes de interfaz individuales, sino que se describen los conceptos de la  aplicación que quiere probar.

Ejemplo de un Test Gherkin

El siguiente es un ejemplo de un Gherkin para buscar “bdd js” en Google:

Given I have loaded Google

When I search for “bdd js”

Then the first result is “BDD with JS: Architecture, Tools & Patterns – GitHub Pages”

Podemos ver que esta prueba nos indica qué hacer y no cómo hacerlo. Está escrito en un lenguaje que tiene sentido para cualquiera que lo lea, y, lo que es más importante, probablemente sea correcto independientemente de cómo se pueda ajustar el producto final. Google podría decidir cambiar completamente su UI, pero mientras la funcionalidad sea equivalente, el Gherkin sigue siendo preciso.

Cucumber.js

Una vez se hayan escrito los casos de prueba en formato Gherkin, se necesita una forma de ejecutarlos. En el mundo JavaScript, tenemos un módulo llamado Cucumber.js que nos permite esto. Cucumber permitir definir código JavaScript que se puede conectar a los diversos steps definidos en los archivos Gherkin. A continuación, ejecuta las pruebas cargando los archivos Gherkin y ejecutando el código JavaScript asociado con cada paso en el orden correcto.

Por ejemplo, en el ejemplo Gherkin anterior, tendría los siguientes steps:

Given(‘I have loaded Google’, function() {});

When(‘I search for {una_cadena_de_caracteres}’, function() {});

Then(‘the first result is {una_cadena_de_caracteres}’, function() {});

En este caso el archivo Gherkin ha sido transformado en formato javascript que sigue la secuencia de pasos del Gherkin. Donde una_cadena_de_caracteres es una variable que será reemplazada por el valor entre comillas en el archivo Gherkin (por ejemplo “bdd js”).

Añadiendo Cucumber en un proyecto

Primero será necesario instalar Cucumber.js. Esto lo podemos fácilmente añadiendo el módulo cucumber mediante npm para el contexto de desarrollo:

npm install –save-dev cucumber
Por convención, todos los  archivos Gherkin se deben situar en el directorio features, y si no se indica, Cucumber buscará en el mismo directorio JavaScript.Una vez instalado necesitaremos ejecutar Cucumber. Esto se puede hacer varias maneras, dependiendo del grado de automatismo que deseemos.

Ejecución manual

Ejecutar Cucumber manualmente es relativamente fácil, y es una buena idea asegurarse de que se puede hacer esto primero, ya que las siguientes soluciones son solo formas automáticas de hacer lo mismo.

Una vez instalado, el ejecutable será ./node_modules/.bin/cucumber.js. Cuando se  ejecuta, necesita saber en qué parte del sistema puede encontrar todos sus archivos requeridos. Estos es: los archivos Gherkin y el código JavaScript que se probará.

Por ejemplo, si tenemos todos los archivos Gherkin en el directorio myFeatures y todo el código JavaScript en mySteps, se puede ejecutar de la siguiente manera:

$ ./node_modules/.bin/cucumber.js ./myFeatures -r ./mySteps

El flag -r es un directorio que contiene archivos JavaScript que se requerirán automáticamente en las pruebas. Para conocer más flags podemos usar la ayuda del cucumber:

$ ./node_modules/.bin/cucumber.js –help

Los directorios indicados se escanean de forma recursiva.

Ejecución mediante script npm

Una vez que hayamos ejecutado Cucumber manualmente, agregarlo a la compilación como una secuencia de comandos npm es sencillo. Simplemente necesitamos agregar el siguiente comando a su paquete.json (sin la ruta completa, dado que npm lo gestiona de automáticamente)

“scripts”: {“cucumber”: “cucumber.js ./myFeatures -r ./mySteps”}

Una vez hecho esto ejecutaremos el comando de la siguiente manera

$ npm run cucumber

Ejecución mediante Grunt y Gulp

En el caso de Grunt usaremos el  grunt-shell.

Una vez instalado añadiremos la configuración a Gruntfile.js:

shell: {cucumber: {command: ‘cucumber.js ./myFeatures -r ./mySteps’}}

Ejecutaremos los tests con

grunt shell:cucumber

El caso de Gulp, es similar al de Grunt y usaremos el gulp-shell con la siguiente configuración.

gulp.task(‘cucumber’, shell.task([‘cucumber.js ./myFeatures -r ./mySteps’]));

Ejecutaremos los tests con

gulp cucumber

Primera prueba Cucumber

Crearemos un proyecto de prueba que nos servirá para probar la configuración de cucumber:

$ npm init$ npm install –save-dev cucumber$ mkdir features steps

Haremos una ejecución manual:

$ ./node_modules/.bin/cucumber.js features/ -r steps/0 scenarios0 steps0m00.000s$

Escribiremos una primera prueba “Saludador”. Para ello definiremos los escenarios en Gherkin en el fichero features/saludar.feature:

Feature: Saludar   Scenario: “Hola” + “mundo”     Given I start with “Hola”     When I add “mundo”     Then I end up with “Hola mundo”   Scenario: “Hola” + “Ricardo”     Given I start with “Hola”     When I add “Ricardo”     Then I end up with “Hola Ricardo”

Si lo hacemos correr

./node_modules/.bin/cucumber.js features/ -r steps/

Obtendremos una Salida de error debido a que los steps de los escenarios no están implementados. En los warnings Cucumber nos da pistas sobre cómo implementar dichos steps:

Implementaremos los steps en steps/saludar.js. Aquí es donde entraríamos en el proceso BDD para generar la solución.

A efectos de este artículo tomaremos la vía rápida:

const defineSupportCode = require(‘cucumber’).defineSupportCode;const assert = require(‘assert’);defineSupportCode(function({ Given, Then, When }) {let answer = “”;Given(‘I start with {string}’, function (input) {// Write code here that turns the phrase above into concrete actions//callback(null, ‘pending’);answer = input;});When(‘I add {string}’, function (input) {// Write code here that turns the phrase above into concrete actions//callback(null, ‘pending’);answer = answer +” “+ input;});Then(‘I end up with {string}’, function (input) {// Write code here that turns the phrase above into concrete actions//callback(null, ‘pending’);assert.equal(answer, input);});});

Si hacemos correr nuevamente las pruebas obtendremos un resultado positivo:

./node_modules/.bin/cucumber.js features/ -r steps/

2 scenarios (2 passed)

6 steps (6 passed)

0m00.006s

Como se puede intuir, podemos seguir definiendo escenarios e implementado los steps que permitan pasarlos.

Reflexiones finales

BDD es una manera fantástica de garantizar que nuestro producto tenga el comportamiento requerido, y Cucumber es una herramienta poderosa que permite hacer transversal, a una organización, la definición del comportamiento válido para una aplicación a través de las pruebas.

El lenguaje Gherkin permite definir escenarios de pruebas y que estas sean entendibles por cualquier parte interesada en el producto dentro de nuestra organización; e incluso que múltiples perfiles con incidencia en el proyecto puedan contribuir en la definición más técnica del comportamiento deseado.

Las implementaciones de los steps en lenguaje específico (en este caso Javascript) seguirá las definiciones hechas en los escenarios y esto garantiza que la implementación del producto se ciña a los requerimientos definidos en dichos escenarios.

¿Te atreves a usar Cucumber?

Únete a nuestra comunidad

#AlwaysLearning

Formación

  • Sensibilización en la importancia de las e-Competences
  • Capacitación Técnica y en Gestión de la Tecnología
  • Formación a medida
  • Adaptación de contenidos propios a formación presencial y online
Buscar

Request Information

Solicitar Información