Cucumber y Java - definiendo test de una manera amigable
Cucumber es un framework que permite definir test para nuestras aplicaciones de una manera verbal. Es decir definir los test con frases entendibles, de forma que cualquier persona que quiera realizar un test no necesite saber programar ya que los definira en texto plano.
Para que te hagas una idea, esto bastaria para definir un test con cucumber:
Feature: Probar calculadora
Mediante este test voy a
hacer pruebas con dos numeros a
ver como se comporta mi aplicacion.
Scenario: Sumatorio de dos numeros
Given dos numeros 2,3
When sumo los dos numeros
And multiplico el resultado por 3
Then resultado debe ser 15
Feature es el nombre de la funcionalidad que queramos, y debajo ponemos la descripcion que queramos.
Luego definimos un Scenario, podemos definir tantos como queramos para nuestras pruebas.En este caso creo Sumatorio de dos numeros porque es lo que voy a probar.
Vemos que tenemos palabras claves (Given, When, And, Then) que definen los distintos pasos del test. (Muy parecido a lo que hace JUnit). Estas palabras veremos que tienen relacion directa con anotaciones en nuestro codigo.
Nuestro test va a consistir en :
Definimos que dados 2 numeros (parametros de entrada 2 y 3), los sumo luego los multiplico por 3 y el resultado debe ser 15.
¿facil y entendible, no? ;-DD
Vamos a generar un proyecto con maven y a integrar este test:
1.Generar un proyecto de maven :
mvn archetype:create -DgroupId=org.dppware.cucumber -DartifactId=CucumberTest
*Voy a editar con Eclipse, asi que mvn eclipse:eclipse para generar el .project y .classpath
Nos quedara algo asi:
2. Editamos el pom.xml para meter la dependencias de cucumber. Tambien especificamos nivel de compilacion y algun parametro para surefire-repors y definimos donde se encuentras los resource que se deben buscar en los test. Quedara algo asi:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.dppware.cucumber</groupId>
<artifactId>CucumberTest</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>CucumberTest</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<cucumber.jvm.version>1.0.2</cucumber.jvm.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-core</artifactId>
<version>${cucumber.jvm.version}</version>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-java</artifactId>
<version>${cucumber.jvm.version}</version>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-junit</artifactId>
<version>${cucumber.jvm.version}</version>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-html</artifactId>
<version>0.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.1</version>
</dependency>
</dependencies>
<build>
<testResources>
<testResource>
<directory>src/test/resources</directory>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.11</version>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
3.Creamos la clase test/java/org/dppware/cucumber/CucumberTest.java con este contenido
4.Creamos un archivo miPrimerTest.feature . Los archivos feature es donde definimos los test que vimos arriba. Creamos este archivo dentro de test/resources/org/dppware/cucumber/miPrimerTest.feature
El contenido del archivo es el que pusimos arriba:
Feature: Probar calculadora
Mediante este test voy a
hacer pruebas con dos numeros a
ver como se comporta mi aplicacion.
Scenario: Sumatorio de dos numeros
Given dos numeros 2,3
When sumo los dos numeros
And multiplico el resultado por 3
Then resultado debe ser 15
5.Ahora que ya hemos definido el test en el feature, pues vamos a preparar el codigo que se ejecutara. Creamos una clase en test/java/org/dppware/cucumber/CucumberTest.java
Con este contenido:
Si nos fijamos mediante expresiones regulares asociamos las anotaciones de .features con el codigo que lo ejecutara. Ademas, vemos como desde la definicion del test este inyectara los valores para hacer el test. Es decir, por ejemplo este paso:
Given dos numeros 2,3
esta relacionado con
@Given("^dos numeros (\\d+),(\\d+)$")
public void given_dos_numeros(int x, int y) {
Los valores 2 y 3 deben ser numericos , de ahi la restriccion rexExp (\\d+) , (\\d+) y vemos como el metodo acepta los 2 argumentos que seran inyectados.
Lo mismo pasa con el ultimo metodo para hacer el Assert del resultado esperado
Then resultado debe ser 15
@Then("^resultado debe ser (\\d+)$")
public void resultado_debe_ser(int x) {
Assert.assertEquals(x,summatory);
}
*Nota, aunque los nombres de los metodos, se parecen a las expresiones regulares, no hace falta que sean iguales.
6. Antes de ejecutar el test, vamos a definir otro Scenario, para probar un test que va bien y otro que va mal (por ejemplo que el resultado sea 16). Al final el .feature quedara asi:
Feature: Probar calculadora
Mediante este test voy a
hacer pruebas con dos numeros a
ver como se comporta mi aplicacion.
Scenario: Sumatorio de dos numeros
Given dos numeros 2,3
When sumo los dos numeros
And multiplico el resultado por 3
Then resultado debe ser 15
Scenario: Sumatorio de dos numeros
Given dos numeros 2,3
When sumo los dos numeros
And multiplico el resultado por 3
Then resultado debe ser 16
7.Si ejecutamos los test, o hacemos clean install de la aplicacion veremos que en las trazas pone que un Scenario fue bien y el otro mal.
Si entramos en la ruta donde genera los reports, es decir en target/cucumber vemos un index.html (que especificamos cuando definimos la anotacion @Cucumber.Options(format = {"pretty", "html:target/cucumber"}) y ahi podemos ver el resultado y nos saca que uno fue bien y otro mal:
Cucumber es una herramienta muy potente para definir test y que nos puede ayudar a hacer TDD de una manera sencilla y agil. Tambien nos permite que una vez definidao el codigo de la prueba, cualquier persona pueda definir sus propios test sin necesidad de conocer el codigo y testear nuestra aplicacion con otras variantes.
El codigo fuente de este ejemplillo que he hecho lo puedes descargar desde aqui:
https://www.dropbox.com/s/hhoqe2a4geemces/CucumberTest.rar
Rock!
Enlaces:
En esta pagina hay ejemplos de como integrar las pruebas de Cucumber con Selenium y hacer pruebas simuladas de Navegador.: http://www.coveros.com/blog/cucumber-jvm-setup
<properties>
<cucumber.jvm.version>1.1.2</cucumber.jvm.version>
</properties>
Y para generar los reports en html tambien hay otra version
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-html</artifactId>
<version>0.2.2</version>
</dependency>
Esta dependencia genera unos reports en html que en Chrome funcionan perfectamente.
Incluso en nuestro codigo podemos usar
@Before
public void init(Scenario scenario) throws Exception {
//Scenario Reference
setScenario(scenario);
}
y con el objeto cucumber.api.Scenario con su metodo .write(String msg) podemos sacar trazas de nuestra ejecucion que luego se podran ver en el reporte HTML en chrome (en firefox no carga bien, quizas es mi version de Firefox...:-( )
getScenario().write("aqui trazo lo que quiero....");
Cuando compileis vereis que las clases han cambiado la estructura de paquetes, con lo cual en las clases basta con cambiar los imports por estos:
import cucumber.api.Scenario;
import cucumber.api.java.Before;
import cucumber.api.java.en.And;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
Para que te hagas una idea, esto bastaria para definir un test con cucumber:
Feature: Probar calculadora
Mediante este test voy a
hacer pruebas con dos numeros a
ver como se comporta mi aplicacion.
Scenario: Sumatorio de dos numeros
Given dos numeros 2,3
When sumo los dos numeros
And multiplico el resultado por 3
Then resultado debe ser 15
Feature es el nombre de la funcionalidad que queramos, y debajo ponemos la descripcion que queramos.
Luego definimos un Scenario, podemos definir tantos como queramos para nuestras pruebas.En este caso creo Sumatorio de dos numeros porque es lo que voy a probar.
Vemos que tenemos palabras claves (Given, When, And, Then) que definen los distintos pasos del test. (Muy parecido a lo que hace JUnit). Estas palabras veremos que tienen relacion directa con anotaciones en nuestro codigo.
Nuestro test va a consistir en :
Definimos que dados 2 numeros (parametros de entrada 2 y 3), los sumo luego los multiplico por 3 y el resultado debe ser 15.
¿facil y entendible, no? ;-DD
Vamos a generar un proyecto con maven y a integrar este test:
1.Generar un proyecto de maven :
mvn archetype:create -DgroupId=org.dppware.cucumber -DartifactId=CucumberTest
*Voy a editar con Eclipse, asi que mvn eclipse:eclipse para generar el .project y .classpath
Nos quedara algo asi:
2. Editamos el pom.xml para meter la dependencias de cucumber. Tambien especificamos nivel de compilacion y algun parametro para surefire-repors y definimos donde se encuentras los resource que se deben buscar en los test. Quedara algo asi:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.dppware.cucumber</groupId>
<artifactId>CucumberTest</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>CucumberTest</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<cucumber.jvm.version>1.0.2</cucumber.jvm.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-core</artifactId>
<version>${cucumber.jvm.version}</version>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-java</artifactId>
<version>${cucumber.jvm.version}</version>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-junit</artifactId>
<version>${cucumber.jvm.version}</version>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-html</artifactId>
<version>0.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.1</version>
</dependency>
</dependencies>
<build>
<testResources>
<testResource>
<directory>src/test/resources</directory>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.11</version>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
3.Creamos la clase test/java/org/dppware/cucumber/CucumberTest.java con este contenido
En Cucumber.options le estamos definiendo que queremos que nos saque los resultados de una forma mas bonita en un html, que encontraremos en la carpeta target/cucumber. Tambien se puede añadir la opcion monochrome=true, que sacara las trazas en color,etc...
@Cucumber.Options(format = {"pretty", "html:target/cucumber"},monochrome = true)
El contenido del archivo es el que pusimos arriba:
Feature: Probar calculadora
Mediante este test voy a
hacer pruebas con dos numeros a
ver como se comporta mi aplicacion.
Scenario: Sumatorio de dos numeros
Given dos numeros 2,3
When sumo los dos numeros
And multiplico el resultado por 3
Then resultado debe ser 15
Con este contenido:
Si nos fijamos mediante expresiones regulares asociamos las anotaciones de .features con el codigo que lo ejecutara. Ademas, vemos como desde la definicion del test este inyectara los valores para hacer el test. Es decir, por ejemplo este paso:
Given dos numeros 2,3
esta relacionado con
@Given("^dos numeros (\\d+),(\\d+)$")
public void given_dos_numeros(int x, int y) {
Los valores 2 y 3 deben ser numericos , de ahi la restriccion rexExp (\\d+) , (\\d+) y vemos como el metodo acepta los 2 argumentos que seran inyectados.
Lo mismo pasa con el ultimo metodo para hacer el Assert del resultado esperado
Then resultado debe ser 15
@Then("^resultado debe ser (\\d+)$")
public void resultado_debe_ser(int x) {
Assert.assertEquals(x,summatory);
}
*Nota, aunque los nombres de los metodos, se parecen a las expresiones regulares, no hace falta que sean iguales.
6. Antes de ejecutar el test, vamos a definir otro Scenario, para probar un test que va bien y otro que va mal (por ejemplo que el resultado sea 16). Al final el .feature quedara asi:
Feature: Probar calculadora
Mediante este test voy a
hacer pruebas con dos numeros a
ver como se comporta mi aplicacion.
Scenario: Sumatorio de dos numeros
Given dos numeros 2,3
When sumo los dos numeros
And multiplico el resultado por 3
Then resultado debe ser 15
Scenario: Sumatorio de dos numeros
Given dos numeros 2,3
When sumo los dos numeros
And multiplico el resultado por 3
Then resultado debe ser 16
7.Si ejecutamos los test, o hacemos clean install de la aplicacion veremos que en las trazas pone que un Scenario fue bien y el otro mal.
Si entramos en la ruta donde genera los reports, es decir en target/cucumber vemos un index.html (que especificamos cuando definimos la anotacion @Cucumber.Options(format = {"pretty", "html:target/cucumber"}) y ahi podemos ver el resultado y nos saca que uno fue bien y otro mal:
Cucumber es una herramienta muy potente para definir test y que nos puede ayudar a hacer TDD de una manera sencilla y agil. Tambien nos permite que una vez definidao el codigo de la prueba, cualquier persona pueda definir sus propios test sin necesidad de conocer el codigo y testear nuestra aplicacion con otras variantes.
El codigo fuente de este ejemplillo que he hecho lo puedes descargar desde aqui:
https://www.dropbox.com/s/hhoqe2a4geemces/CucumberTest.rar
Rock!
Enlaces:
En esta pagina hay ejemplos de como integrar las pruebas de Cucumber con Selenium y hacer pruebas simuladas de Navegador.: http://www.coveros.com/blog/cucumber-jvm-setup
ACTUALIZACIONES:
He estado investigando un poco mas y hay otra version mas nueva de cucumber-jvm , la 1.1.2<properties>
<cucumber.jvm.version>1.1.2</cucumber.jvm.version>
</properties>
Y para generar los reports en html tambien hay otra version
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-html</artifactId>
<version>0.2.2</version>
</dependency>
Esta dependencia genera unos reports en html que en Chrome funcionan perfectamente.
Incluso en nuestro codigo podemos usar
@Before
public void init(Scenario scenario) throws Exception {
//Scenario Reference
setScenario(scenario);
}
y con el objeto cucumber.api.Scenario con su metodo .write(String msg) podemos sacar trazas de nuestra ejecucion que luego se podran ver en el reporte HTML en chrome (en firefox no carga bien, quizas es mi version de Firefox...:-( )
getScenario().write("aqui trazo lo que quiero....");
Cuando compileis vereis que las clases han cambiado la estructura de paquetes, con lo cual en las clases basta con cambiar los imports por estos:
import cucumber.api.Scenario;
import cucumber.api.java.Before;
import cucumber.api.java.en.And;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
Muchas gracias Daniel. He podido comprender e interiorizar el uso y la potencia de Cucumber gracias a este post.
ResponderEliminarUn saludo.
Excelente muchas gracias, tienes bastante talento ��
ResponderEliminar