Haciendo BDD con Cucumber
0. Índice de contenidos.
1. Entorno
Este tutorial está escrito usando el siguiente entorno:
- Hardware: Portátil Intel Core 2 CPU T7200 @ 2.00GHz x 2
- Sistema Operativo: Ubuntu 12.04 LTS x32
- Sublime Text 2
2. Introducción
Cucumber es una herramienta, escrita originalmente en Ruby, que ejecuta descripciones funcionales en texto plano como test automáticos, aprovechando las ventajas del BDD como puede ser acercar la capa de negocio y tecnología de una empresa, permitiendo que no solo se desarrollen bien las funcionalidades, sino que se desarrollen las funcionalidades que mas valor van a aportar al usuario, a la vez que definimos casos de prueba y documentamos un proyecto.
La idea principal es que pueda ser entendido y usado no solo por desarrolladores sino por los clientes y gente de negocio.
El lenguaje que usa Cucumber para definir los requisitos se llama Gherkin, el cual nos permite traducir esas especificaciones en un lenguaje cercano al natural en especificaciones de test en el lenguaje que queramos, un ejemplo de Gherkin sería el siguiente:
Feature: Search courses In order to ensure better utilization of courses Potential students should be able to search for courses Scenario: Search by topic Given there are 240 courses which do not have the topic "biology" And there are 2 courses A001, B205 that each have "biology" as one of the topics When I search for "biology" Then I should see the following courses: | Course code | | A001 | | B205 |
3. ¿En qué consiste Gherkin?
Gherkin es el lenguaje que entiende Cucumber, es un DSL legible para gente no técnica, que permite definir el comportamiento del software sin detallar como está implementado, además de que nos permite documentar las funcionalidades a la vez que escribimos casos de prueba automáticos.
Otras ventajas que nos proporciona usar Gherkin y Cucumber son:
- Fáciles de leer
- Fáciles de entender
- Fáciles de Parsear
- Fáciles de discutir
Gherkin es un lenguaje que usa el indentado para definir la estructura, de manera que los saltos de linea dividen las diferentes declaraciones, la mayoría de las lineas empiezan con palabras clave. El parser divide el texto en Features ( Características ), Scenarios y Steps, cuando pasas los casos de prueba, el parser busca un Step con ese nombre. Los Steps son los análogos de los Métodos en Java o las Funciones en Javascript.
Gherkin está localizado en muchos idiomas entre ellos el español:
# language: es Característica: adición Para evitar hacer errores tontos Como un ser humano Quiero saber la suma de los números Esquema del escenario: Sumar dos números Dado que he introducido <entrada_1> en la calculadora Y que he introducido <entrada_2> en la calculadora Cuando oprimo el <botón> Entonces el resultado debe ser <resultado> en la pantalla Ejemplos: | entrada_1 | entrada_2 | botón | resultado | | 20 | 30 | add | 50 | | 2 | 5 | add | 7 | | 0 | 40 | add | 40 |
Generaría
# encoding: utf-8 begin require 'rspec/expectations'; rescue LoadError; require 'spec/expectations'; end require 'cucumber/formatter/unicode' $:.unshift(File.dirname(__FILE__) + '/../../lib') require 'calculador' Before do @calc = Calculador.new end Dado /que he introducido (\d+) en la calculadora/ do |n| @calc.push n.to_i end Cuando /oprimo el (\w+)/ do |op| @result = @calc.send op end Entonces /el resultado debe ser (.*) en la pantalla/ do |result| @result.should == result.to_f end
Cada feature ( característica ) se define en un archivo, una característica normalmente consiste en una serie de escenarios, el texto entre Característica y «Esquema del escenario» permite definir libremente ya que este texto no será usado para ninguna funcionalidad de Cucumber, es meramente descriptivo.
Este código nos generará un esqueleto ( dependiendo del lenguaje en el que vayamos a producir los test y el adaptador que estemos usando ), el cual pasará los test con los distintos casos que le hayamos definido. Luego será nuestra tarea la de definir los casos de prueba que comprobarán las diferentes características.
Se pueden diferenciar claramente tres grupos que cumplen funciones distintas:
- Feature: Aquí es donde indicamos el nombre de la característica a probar.
- Scenario: Esta «keyword» describe los distintos escenarios que van a probar las diferentes posibilidades.
- Given (Dado) : El propósito de los «Dado» es el de poner al sistema en el estado deseado para pasar los test deseados, antes de que el usuario ( o un sistema externo ), interactúe con el sistema.
- When ( Cuando ) : En este caso el propósito de los «Cuando» es el describir la acción que realiza el usuario, la cual vamos a probar.
- Then ( Entonces ) : El propósito de los «Entonces» es observar los resultados, estas observaciones han de ser realizadas desde el punto de vista de negocio y el valor para el usuario. Estas observaciones también deben de estar en algún sitio visible para el usuario, no en una base de datos o capas inferiores del sistema.
- And, But ( Y, Pero ): Estas «keywords» están destinadas a aumentar la legibilidad y pueden ser usadas en vez de definir repetidas veces cualquiera de las anteriores.
Al ejecutar Cucumber, buscará un Step que coincida con cada definición, siendo irrelevante la «keyword» usada para otra cosa que no sea el orden, esto cambia ligeramente dependiendo el lenguaje que estemos probando.
4. Ejemplos Prácticos
Podemos encontrar ejemplos en distintos lenguajes como:
Java, mostrando el archivo desde el que se parte y el archivo que se generaría, incluyendo algún test de ejemplo ya implementado, Feature &
Step.
Y Ruby Feature & Steps.