¿Te gustaría detectar bugs incluso antes de que se escriban? Sería increíble encontrar bugs que todavía no han «nacido» y que se están  en la mente del desarrollador,  ¿verdad?  Te voy a explicar en qué consiste para mí el Story Testing y cómo aplicar esta técnica en el mundo real.

Bien, ¿qué es eso del Story Testing? Seguro que has oído hablar de Acceptance Test–Driven Development (ATDD), Behaviour Driven Development (BDD), Story Test Driven Development (SSD), Specification By Example (SBE), Example Driven Development (EDD), etc. Son enfoques ligeramente diferentes para un mismo objetivo: implementar correctamente lo que el cliente pide, y a la primera. Cuando hacemos Story Testing, lo que hacemos es utilizar alguna de estas técnicas. Yo prefiero este término, ya que lo que al final hacemos es asegurarnos de que la historia de usuario hace lo que se ha pedido y tiene pocos o ningún error (lo de ningún error ya es más difícil trabajando con software…).

Si haces Story Testing  (independientemente del «sabor» que elijas: ATDD, BDD, SBE, etc.), los tests (o ejemplos) se crean antes de implementar la historia de usuario. Pero al contrario que en el testing tradicional, donde los testers son los «amos» de los tests, en este proceso participan los testers, desarrolladores y negocio.

Tiene una ventaja adicional: los tests al ser también ejemplos de uso, te sirven como documentación «ejecutable» de tu sistema, de forma que nunca quedará obsoleta (o los tests comenzarán a fallar…).

Al lío:

  • Partimos de la historia de usuario que previamente ya se ha analizado y escrito por el equipo (desarrolladores, testers, product owner, …). Real life fact: En algunos equipos ágiles, las historias de usuario se escriben directamente a partir del trabajo de un analista y hay poca interacción directa del equipo de desarrollo con negocio o el cliente.
  • Creamos los tests. Estos tests serán ejemplos de la funcionalidad que se espera de la historia de usuario. Servirán de guía para implementar la historia. Ten en cuenta que a partir de aquí usar los términos ejemplo o test será lo mismo, ya que siempre serán casos de test ejecutables que validarán que la historia de usuario esté bien implementada. Insisto: a partir de aquí ejemplo=test. Grábatelo en la mente.
  • Comienza con los casos más básicos y ve complicándolo. Yo suelo hacerlo en este orden: happy-path (casos positivos), casos negativos y casos con errores,… Real life fact: Este paso suelo hacerlo junto con el desarrollador de la historia, consultando a negocio en caso necesario. Al ejecutar estos tests fallarán, en el siguiente paso se escribe el código que hace que esos tests pasen.
  • Se va escribiendo el código que implementa la historia de forma iterativa con el paso anterior, hasta que todos los ejemplos se ejecutan correctamente bien. Este desarrollo se hace siguiendo TDD: se escriben los tests unitarios que fallan, el código que hace que pasen y se refactoriza.
  • Se integran el desarrollo y los tests y vuelta a empezar.

Debes tener en cuenta esto:

  1. Tienes que escribir los tests de forma que los entiendan todos los implicados, y eso incluye a tus compañeros de negocio…. Aquí es imprescindible que la herramienta que utilices te permita expresar los tests (recuerda ¡también son ejemplos!) en un lenguaje claro. Te cuento como hacerlo en el siguiente apartado 🙂
  2. Los ejemplos, tienen que cubrir todas las características de la historia de usuario y sólo esas. Ni más ni menos. No escribas más de un ejemplo o test para una misma característica ni incluyas ejemplos para características que no están en la historia de usuario.
  3. Si es posible, es recomendable ejecutar estos tests directamente en la capa de lógica de negocio. Aun así, siempre puedes ejecutarlos como lo haría un usuario,  desde la interfaz de usuario.
  4. Esta técnica no sustituye a TDD (Test Driven Development), deberías seguir escribiendo tus tests unitarios para asegurar que tu código es correcto. Las dos técnicas son complementarias.

Herramientas

Los ejemplos deben escribirse con un lenguaje claro y entendible por cualquiera sin conocimientos de programación o testing. Los frameworks tradicionales de testing como JUnit son un poco «áridos» para la gente de negocio. Normalmente estos compañeros entienden bien Excel o Word. La solución es utilizar alguna herramienta que exprese los tests en un formato muy claro. Aquí van algunas:

La que YO uso normalmente:

  • Fitnesse es un servidor web tipo wiki y una herramienta para automatizar tests de aceptación.  Los tests se escriben en formato de tablas y son muy sencillos de comprender por todo el mundo. El  código para «conectar» los tests con tu software no debería ser muy complicado, pero puede ser bastante difícil si tu sistema no está pensando para ello desde el principio. Tiene unos cuantos de plugins que te facilitarán la vida en este sentido. Enfocado a ATDD.

Yo NO las he usado pero tienen buena pinta:

  • Cucumber framework orientado a BDD. Soporta un montón de lenguajes de programación.
  • Concordion para automatizar con el enfoque SBE (Specification by Example). Soporta Java y algunas características también están disponibles para C#.
  • Robot Framework es un framework para crear tests de aceptación automáticos, desde un punto de vista de desarrollo tipo ATDD.
  • Spock framework de test y especificación para aplicaciones Java y Groovy.

Algunas de estas herramientas permiten combinarse con Selenium,  que te será útil si necesitas hacer tests de interfaz de usuario.

-> Si quieres recomendar (o criticar) alguna más, envía un comentario.

Un ejemplo práctico

En una ocasión teníamos que implementar un sistema que bajo determinadas condiciones hacía una exportación de datos a un sistema externo.

A grosso modo la historia decía:

Como administrador quiero que cada vez que se dé de alta un cliente nuevo o se modifique alguno de sus datos personales en la BBDD de clientes, se traspasen ciertos datos a la BBDD de contabilidad, para tener siempre sincronizadas las las BBDD de clientes  y contabilidad.

En la BBDD de clientes teníamos estos campos (he simplificado un el ejemplo):

NumeroCliente, Campos con datos personales, NumeroClienteContabilidad, FechaTranspasoContabilidad

Comenzamos a preparar el test con los casos más sencillos en FitNesse:

NumeroCliente DatosPersonales NumeroClienteContabilidad FechaTranspasoContabilidad Traspasar?
1 Modificados 1001 1/1/2017 SI
2 SinCambios 1002 1/12017 NO
3 Nuevo SI

Bastante sencillo, ¿no?. Paso a describir el diálogo con el que evolucionamos los tests:

Tester: Pregunto, ¿qué ocurre si hay un cliente con un NumeroClienteContabilidad asignado pero con la FechaTranspasoContabilidad nula? ¿O al revés?

Desarrollador: ¡Eso no puede ocurrir!

Tester: Mmmm… vamos a asegurarnos de eso.

Una búsqueda rápida en la base de datos reveló que había unos cuantos miles de casos así. O bien porque no se realizó el proceso correctamente en su día o por algún cambio en los requerimientos en el pasado. Pero el caso es que SÍ podía ocurrir.

Primer bug detectado antes del desarrollo: Se había asumido que este caso no se podía dar, pero no era así. El sistema se hubiera comportado de alguna forma errática en este caso.

Así que completamos la tabla:

NumeroCliente DatosPersonales NumeroClienteContabilidad FechaTranspasoContabilidad Traspasar?
1 Modificados 1001 1/1/2017 SI
2 SinCambios 1002 1/12017 NO
3 Nuevo SI
4 Modificados 1004  – Error
5 Modificados 1/1/2017 Error
6 Modificados SI
7 Sin Cambios 1006 NO
8 Sin Cambios 1/1/2017 NO
9 Sin Cambios NO

Tester: Espera, ¿Por qué se da un error en los casos del cliente 4 y 5?

Desarrolador: Mmmm, es un caso en que los datos están mal así que sacaré siempre un error en el log y ya está.

Tester: Deberíamos hablar con el analista y con negocio y decidir juntos qué hacer…

Después de hablar con el experto de Contabilidad se acordó que se traspasarían los datos aunque alguno de esos campos no fuera consistente y se actualizarían los campos «sucios» tras el traspaso.

Segundo bug detectado antes del desarrollo: Contabilidad quería que el sistema se comportara de una forma diferente a la que el equipo de desarrollo pensaba implementar. Una simple conversación evitó programar una cosa que no iba a servir.

La tabla con los tests quedó como algo así:

NumeroCliente DatosPersonales NumeroClienteContabilidad FechaTranspasoContabilidad Traspasar?
1 Modificado 1001 1/1/2017 SI
2 SinCambios 1002 1/12017 NO
3 Nuevo SI
4 Modificado 1004  – SI
5 Modificado 1/1/2017 SI
6 Modificado SI
7 SinCambios 1006 NO
8 Sin Cambios 1/1/2017 NO
9 Sin Cambios NO

De esta experiencia sacamos dos conclusiones:

  • El desarrollador daba por sentado que si la  combinación de campos no era consistente debía sacar un error. Pero negocio tenía otras necesidades. Se hubiera introducido un bug que habría que corregir más adelante.
  • Al hacernos las preguntas correctas antes de escribir el código, supimos realmente lo que necesitaba nuestro cliente y no se perdió tiempo reescribiendo código y arreglando errores.

En resumen

Este tipo de testing se enmarca dentro de las metodologías y técnicas de Agile Testing, en el que las pruebas de software siguen los mismos principios que el desarrollo ágil.  Las metodologías ágiles no ven el testing como una fase separada, sino como parte integral del desarrollo de software, al igual que la programación.

Esta técnica te ayudará a implementar correctamente lo que tu cliente te ha pedido. Podrás detectar bugs que todavía están en la «mente» del equipo, ya sea por malentendidos o debidos a dar por sentado ideas que no son correctas. Tu base de tests te servirá como una documentación «viva» de tu sistema y no quedará obsoleta.

¡Espero que te sea útil! Déjame un comentario con tu opinión 🙂