Posts Tagged Testing

Embajador en los Agile Testing Days 2011 #agiletd

Me alegro mucho de poder presentarme como el primer embajador de España en los Agile Testing Days que, a la sazón, organiza otro año más un español afincado en Alemania. Voy a intentar organizar mi agenda para poder estar en Noviembre en este evento que cada año va teniendo más y más nivel gracias al empuje de la editorial Díaz & Hilterscheid, que algunos ya conoceréis por publicaciones en papel como Agile Record o Testing Experience. Echad un vistazo al programa si no me creéis y seguid la actividad en twitter en y con el hashtag #agiletd.

¿Nos vemos en Potsdam (cerca de Berlín) del 14 al 17 de Noviembre?

Tags: , ,

Una de Concordion

Con esto del Agile Open Spain 2009 estoy dejando de mano muchas cosas, pero no quiero abandonar el blog, así que aunque sean casi “microblogs” voy a intentar no dejar de escribir.

Dicho esto, voy a aprovechar que para el próximo miércoles en el grupo de Agile Spain en Madrid me he comprometido a hacer una presentación de 5 minutos para defender el tema “Pruebas de Aceptación Automatizadas con Concordion” y voy a dejar un par de apuntes aquí.

En el estupendo blog “Dos Ideas” he visto hace poquísimo un artículo con un par de screencasts en español sobre cómo usar Concordion + Selenium. Muy útil.

Para los que utiliceis .NET y queráis usar Concordion.NET, éste es vuestro blog (en inglés).

Lo siento, no hay tiempo para más. :(

Tags: , ,

AAFT, GTAC y automatización de pruebas en España

Estaba viendo una entrevista grabada durante la conferencia Agile2008 a Elisabeth “testobsessed” Hendrikson acerca de una iniciativa bastante interesante llamada Agile Alliance Functional Testing Tools Group (AAFT para que nos entendamos). Hay una lista de correo en Yahoo a la que ya me he suscrito y a través de la cual me he enterado de que Google organiza la cuarta “Google Test Automation Conference” dedicada a las pruebas para la web. Si alguno de vosotros está interesado en asistir, que sepa que este año será en Zurich (Suiza) entre los días 21 y 22 de Octubre. Y si alguno es más valiente y se atreve a proponerse para dar una charla, el “call for proposals” ya está abierto y termina el 1 de Agosto.

Me pregunto qué foros similares hay en España. Me refiero tanto a conferencias dedicadas exclusivamente a la automatización de pruebas como a grupos donde discutir sobre herramientas orientadas a la automatización de pruebas. En el primer grupo yo conozco la conferencia QA&TEST, que se celebra anualmente en Bilbao y que por lo que tengo entendido se orienta sobre todo a las pruebas en entornos de software empotrado (perdón, embebido). Pero en el segundo es que ni eso. ¿Qué pasa en España que no nos organizamos en grupos para aprender? Bueno, al menos en Agile Spain estamos invirtiendo esa tendencia, demostrando que estas inversiones de tiempo empleadas en reunirnos con desconocidos para compartir experiencias y conocimientos (pongo el ejemplo del grupo de Madrid o el del grupo de Barcelona) son inversiones muy rentables.

Tags: , , ,

Salir de la crisis

Estaba viendo que me había llegado el boletín mensual de Infojobs y en el decía que han crecido un 7% sus ofertas de empleo relacionadas con la calidad del software. Esto me ha hecho plantearme por qué. ¿Por qué se solicita ahora más ayuda para asegurar la calidad de los desarrollos?

a) Porque ahora hay que reducir costes y los errores son costosos (muy costosos)
b) Porque el sector ha madurado y se ha dado cuenta de que así no se puede seguir y se necesitan expertos en asegurar la calidad de los desarrollos.
c) Quizás es que se hayan dejado de contratar desarrolladores porque ya no hay desarrollos y, proporcionalmente, parezca que han subido las necesidades de otros puestos.

Obviamente descarto la opción b) por irreal y la c) porque me parece difícil de que sea así (es una sensación). En cambio, la opción a) me parece plausible. Es posible que, por fin, esté calando el mensaje de los 70 de que el coste de los errores de desarrollo se multiplica en varios órdenes de magnitud cuando éstos llegan a producción y en España estemos empezando a salir de la crisis del software.

Tags: , ,

Pruebas funcionales automatizadas de una aplicación web

Hoy voy a resumir cómo automatizar las pruebas funcionales de una aplicación web utilizando:
  • Maven. Con Maven gestionamos el ciclo de vida de la construcción y las pruebas, así como las dependencias entre artefactos.
  • Cargo. Con este plugin Maven realizamos el despliegue de la aplicación web en el contenedor de nuestra elección.
  • Selenium Webdriver. Con este framework y el correspondiente plugin Maven ejecutamos las pruebas funcionales.
  • Jetty. Éste es el contenedor web de mi elección. (Podría haber sido Tomcat, Glassfish o cualquier otro).
  • JUnit. Como framework de pruebas.
  • Wicket. Éste es el framework web de mi elección.

Todo el código fuente lo tenéis disponible en GoogleCode.

Pruebas unitarias

En Eclipse y con m2eclipse he creado el proyecto raíz con dos módulos: web (de tipo war) y web-integration-test (de tipo pom). El proyecto web lo he creado con el arquetipo “org.apache.wicket:wicket-archetype-quickstart:1.4-rc1″ y luego lo he tocado un poco.

< ?xml version="1.0" encoding="UTF-8"?>
 
  shopaas  shopaas  0.0.1-SNAPSHOT  4.0.0 shopaas web 
war Web Application 0.0.1-SNAPSHOT UI wicket para Shop As A Service   shopaas-web         src/main/resources          src/main/java         **             **/*.java                  src/test/java         **             **/*.java          
 
    maven-compiler-plugin    true         1.5     1.5     true     true        
    org.mortbay.jetty    maven-jetty-plugin         10            
8080       60000                   
    maven-eclipse-plugin         true                org.apache.wicket   wicket   ${wicket.version}       org.slf4j   slf4j-log4j12   1.4.2       log4j   log4j   1.2.14       junit   junit   4.5   test       org.mortbay.jetty   jetty   ${jetty.version}   provided       org.mortbay.jetty   jetty-util   ${jetty.version}   provided       org.mortbay.jetty   jetty-management   ${jetty.version}   provided    
  6.1.14  1.4-rc1 

No quiero entrar en detalles sobre cómo es una aplicación Wicket, pero sí explicaré los dos detalles más importantes:

Si quiero desplegar la aplicación en Jetty no tengo más que ejecutar Maven con el “goal” jetty:run, pero esto sólo nos sirve para probar manualmente nuestra aplicación. (Por cierto, el puerto 8080 es el puerto por defecto, pero me gusta explicitar esta configuración).

Wicket proporciona la clase WicketTester, que permite probar la aplicación fuera del contenedor, mediante una simulación del mismo. De esta manera podemos hacer pruebas unitarias de todos los componentes de nuestra GUI sin necesidad de empaquetarla y desplegarla. Más adelante, en futuros artículos, tengo previsto entrar en detalle en cómo desarrollar la GUI con Wicket haciendo TDD.

package shopaas;

import junit.framework.TestCase;import org.apache.wicket.util.tester.WicketTester;

/** * Simple test using the WicketTester */public class TestHomePage extends TestCase{ private WicketTester tester;

  public void setUp() {  tester = new WicketTester(new WicketApplication()); }

 public void testRenderMyPage() {  //start and render the test page  tester.startPage(HomePage.class);

  //assert rendered page class  tester.assertRenderedPage(HomePage.class);

  //assert rendered label component  tester.assertLabel("message", "If you see this message wicket is properly configured and running"); }}

Esta prueba es muy simple, pero lo suficiente como para ver “por dónde van los tiros”. Como podéis comprobar, llegados a este punto podemos tener las pruebas unitarias de nuestra aplicación web completamente automatizadas y, por tanto, incluidas en nuestro sistema de integración continua sin mayor problema.

Pruebas funcionales

Pruebas funcionales o de integración son términos muy usados pero no tengo claro que todo el mundo entienda lo mismo cuando los usa. Lo que yo estoy llamando aquí pruebas funcionales o de integración son aquellas en las que pruebo el sistema desplegado (hasta donde se puede razonablemente). Pues bien, lo que voy a enseñar ahora es cómo desplegar de manera automática el war de nuestra aplicación y lanzar (automáticamente también) las pruebas.

Para esto he usado Cargo y he modificado el ciclo de vida de varios plugins (compiler, surefire y el propio cargo) para que se ejecuten en el orden adecuado. Además, he usado Selenium Webdriver para escribir y ejecutar las pruebas.

Al ejecutar (desde el proyecto raiz) Maven con el goal “integration-test”, el propio Maven estudia las dependencias entre artefactos y empaqueta el war (y ejecuta sus pruebas) antes de pasar a desplegar ese war en un Jetty 6 que se arranca y detiene solamente para ejecutar las pruebas de integración.



 4.0.0 
  shopaas  shopaas  0.0.1-SNAPSHOT  web-integration-test 
pom Functional Tests      shopaas   web   0.0.1-SNAPSHOT   war       junit   junit   4.5   test         org.openqa.selenium.webdriver   webdriver-htmlunit   0.6.685       org.openqa.selenium.webdriver   webdriver-support   0.6.685         org.mortbay.jetty   jetty   ${jetty.version}   provided       org.mortbay.jetty   jetty-util   ${jetty.version}   provided       org.mortbay.jetty   jetty-management   ${jetty.version}   provided       
 
    org.apache.maven.plugins    maven-compiler-plugin         1.5     1.5     true     true                          testCompile                   
    org.apache.maven.plugins    maven-surefire-plugin          
integration-test             test                   
    org.codehaus.cargo    cargo-maven2-plugin         false                          shopaas        web        war 
         /                          

               start 
pre-integration-test             start                      stop 
post-integration-test             stop                      
 
   jetty6x       true    
    6.1.14       
 
      org.codehaus.cargo      cargo-maven2-plugin                     jetty6x        embedded               
         8080         medium               
          

El único test que he incluido como prueba de concepto contiene dos tipos de prueba (una con Webdriver y otra sin él, la anotada con @Ignore).

package shopaas.web.integration.test;

import static org.junit.Assert.assertEquals;

import java.net.HttpURLConnection;import java.net.URL;

import org.junit.Before;import org.junit.Ignore;import org.junit.Test;import org.openqa.selenium.WebDriver;import org.openqa.selenium.htmlunit.HtmlUnitDriver;

public class WebappTest {

   public void testCallIndexPage() throws Exception {  URL url = new URL("http://localhost:8080/");  HttpURLConnection connection = (HttpURLConnection) url.openConnection();  connection.connect();  assertEquals(200, connection.getResponseCode()); }

 private WebDriver driver;

  public void setUp() {  driver = new HtmlUnitDriver(); }

  public void testHomepage() {  driver.get("http://localhost:8080/");  assertEquals("Wicket Quickstart Archetype Homepage", driver.getTitle()); }

}

He utilizado el HtmlUnitDriver que, aunque también es una emulación de una navegador, para mi es suficiente, no me complica mi entorno y además es más rápido. Pero si quisiera utilizar Firefox, Safari o Internet Explorer, no tendría más que cambiar el driver correspondiente. Lógicamente, podemos tener la misma prueba con un driver diferente y estaremos asegurando que nuestra aplicación funciona para varios navegadores. Mmmmm, veo que he captado vuestra atención… :-)

Problemas encontrados

Al poner todo esto en pie he estado bastante tiempo atascado porque cada vez que ejecutaba las pruebas de integración obtenía un mensaje de error en Jetty diciendo que no era capaz de arrancar la aplicación porque “No suitable Log constructor”. No entiendo de dónde sale el dichoso commons-logging, pero el caso es que poniendo el fichero commons-logging.properties en el classpath de la aplicación web (para que se empaquete en el war), todo pasó a funcionar perfectamente.

org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog

El otro inconveniente que tuve es más un detalle al que prestar atención que otra cosa. Se trata del valor del contexto que hay que poner en la configuración de Cargo, que debe coincidir con el valor usado en el URL de la aplicación en nuestras pruebas y en el fichero web.xml de la aplicación web.

 
    org.codehaus.cargo    cargo-maven2-plugin         false                          shopaas        web        war 
         /                          

                                    ...       

Bien, creo que esto es todo. Si tenéis interés y el código de ejemplo no es suficiente, no dudéis en preguntarme y trataré de ayudaros.

Tags: , , , , , , ,

Métodos estáticos y pruebas unitarias

El año pasado :-) he comenzado el desarrollo de un plug-in para Concordion sin pruebas unitarias. “¡Vaya tío chungo!”, estaréis pensando ahora mismo. Bueno, en cierto modo tenéis razón. Pero tengo una buena excusa. :-)

El caso es que he copipegado código del ejemplo de editor multipáginas que viene con Eclipse y también del WicketBench (un plugin para trabajar con Wicket del que pretendo plagiar más de una idea). Y resulta que este código “heredado” hace un uso bastante prolijo de métodos estáticos para obtener información de contexto y, sobre todo, de la plataforma. Y me viene al pelo el reciente artículo de Misko Hevery donde explica por qué los métodos estáticos son tan malos para las pruebas y delatan diseños deficientes.

En resumen: no tengo pruebas unitarias de mi código porque no puedo sustituir las llamadas a métodos estáticos por ningún tipo de doble. Cualquier colaborador puedo sustituirlo más o menos fácilmente con un doble (p.ej. un mock), pero un método estático está pegado “a fuego” a una clase, y no puedo sustituir una clase por otra… :-(

Claro está que estoy cambiando el código para encapsular las llamadas a métodos estáticos en clases de colaboración que pueda sustituir en mis pruebas. Así acoto el problema, tal y como Eric Evans aconseja al explicar el “anticorruption layer” (capa anticorrupción), y mejoro la facilidad para escribir pruebas para mi diseño y, por tanto, mejoro también mi diseño.

Tags: , ,

Sustitución fácil de colaboradores con Mockito

Acabo de probar Mockito y creo que por fin he encontrado el framework de mocks que necesitaba. Crear “stubs” para sustituir a los colaboradores en las pruebas con EasyMock o jMock me resultaba muy laborioso, en cambio con Mockito es muy fácil.

El ejemplo:

  public void testComprarUnProducto() {  TerminalPuntoDeVenta tpv = new TerminalPuntoDeVenta(100,logger);

  CodigoProducto codigo = new CodigoProducto("FANTA 33CL","1234567890");  DispositivoEscaner mockEscaner = mock(DispositivoEscaner.class);  when(mockEscaner.scan()).thenReturn(codigo);  tpv.setEscaner(mockEscaner);

  RepositorioProductos mockRepositorioProductos = mock(RepositorioProductos.class);  Producto producto = new Producto(codigo);  producto.setPrecio(10);  when(mockRepositorioProductos.buscarProducto(codigo)).thenReturn(producto);  tpv.setRepositorioProductos(mockRepositorioProductos);

  tpv.setImpresora(mock(DispositivoTicket.class));

  tpv.iniciarCompra();  tpv.scan();  tpv.finalizarCompra();  double resultado = tpv.cerrarCaja();  assertEquals(110,resultado,0); }

Los métodos estáticos mock y when son la clave, especialmente when, porque en vez de liarnos a grabar expectations como con otros frameworks, con Mockito decimos cuando llamen al objeto sustituido a tal método y con tales parámetros, entonces devuelve tal resultado. Mucho más intuitivo.

Además, como estoy intentando “quitarme” de las pruebas que comprueban las colaboraciones, me viene genial; aunque si quisiera, no tengo más que hacer los verify que también haría con los otros.

Actualización:
He sacado un rato y he escrito el mismo ejemplo pero con EasyMock.

  public void testComprarUnProductoConEasymock() {  TerminalPuntoDeVenta tpv = new TerminalPuntoDeVenta(100,logger);

  CodigoProducto codigo = new CodigoProducto("FANTA 33CL","1234567890");  DispositivoEscaner mockEscaner = createMock(DispositivoEscaner.class);  mockEscaner.scan();  expectLastCall().andReturn(codigo);  tpv.setEscaner(mockEscaner);

  RepositorioProductos mockRepositorioProductos = createMock(RepositorioProductos.class);  Producto producto = new Producto(codigo);  producto.setPrecio(10);  mockRepositorioProductos.buscarProducto(codigo);  expectLastCall().andReturn(producto);  tpv.setRepositorioProductos(mockRepositorioProductos);

  DispositivoTicket mockImpresora = createNiceMock(DispositivoTicket.class);  tpv.setImpresora(mockImpresora);

  replay(mockEscaner);  replay(mockImpresora);  replay(mockRepositorioProductos);

  tpv.iniciarCompra();  tpv.scan();  tpv.finalizarCompra();  double resultado = tpv.cerrarCaja();  assertEquals(110,resultado,0); }

Tags: , ,

Code Coverage en Eclipse

Aunque se supone que estoy de vacaciones… no he podido resistir el hacer un ejercicio (que publicaré en breve en este blog) sobre Refactoring. Pero quería ver cómo de buenos eran mis tests y, la verdad, no me siento cómodo con el plugin de Cobertura para Maven: quería algo más integrado con Eclipse. Para ello he estado mirando los proyectos TPTP de Eclipse y EclEmma. Ambos están basados en Emma.

Después de buscar y buscar cómo instalar el módulo de code coverage de TPTP me he encontrado con que han abandonado el desarrollo para usar justamente EclEmma. Bueno, eso me ha simplificado el trabajo. :-)

Así pues, después de instalar EclEmma, probar la cobertura de mis tests JUnit ha sido muy fácil. Simplemente he seguido las instrucciones. (Ejem, he de reconocer que las seguí después de ver que me estaba calculando la cobertura ¡¡de los propios tests!!)

Para que no incluya nuestros tests en el informe de cobertura hay que:

  • pulsar en el menú “Run / Coverage”,
  • seleccionar la configuración de nuestro test,
  • pulsar en la pestaña “Coverage”
  • y desmarcar la carpeta correspondiente (en mi caso src/test/java porque uso Maven)

Como suponía, mi cobertura era del 100%. :-)

De todos modos, no tener un plugin estable de Emma para Maven2 hace difícil el incorporarlo al proceso de integración continua (puesto que yo he optado por tenerlo todo con Maven2 y no usar Ant ni otros procesos añadidos). En cualquier caso, en cuanto pueda lo probaré a ver qué tal…

P.S.
Si alguien tiene interés, incluyo el enlace a una presentación sobre EclEmma de la EclipseCon 2008 que puede aclarar cómo funciona por dentro (incluidas referencias a OSGi).

Tags: , , , , ,

Acceptance Test Driven Development

El miércoles tengo que impartir un taller de TDD (Test Driven Development) en DEGESYS y, aunque parto ya del mismo taller que impartí hace ya varios meses, quería buscar nuevas ideas para enriquecerlo y he encontrado esta presentación bastante interesante.

Por cierto, el libro de Manning sobre TDD y Acceptance TDD es también excelente.

Tags: ,

Concordion

Este fin de semana he estado ayudando a “mavenizar” el proyecto Concordion: un framework para pruebas funcionales que, en mi modesta opinión, será el sustituto de Fit en muy poco tiempo.
Echadle un vistazo porque merece la pena, aunque aún le faltan muchas cosas

Tags: , , ,