Estilos de TDD: un voto para London

Hace un tiempo escribí sobre los estilos de TDD e intenté hacerlo de forma objetiva. Ahora pretendo continuar con la cuestión pero dando mi opinión.

No creo que haya un estilo que sea universalmente mejor que otro (no silver bullet). Creo que un determinado contexto puede resultar más conveniente utilizar uno u otro estilo. Personalmente me ocurre que en los contextos en los que suelo trabajar encuentro más conveniente una utilizar una estrategia del estilo London, o para ser más preciso: la propuesta de Freeman & Pryce. Para que se entienda mi posición explico un poco las generalidades de los contextos en los que suelo trabajar.

En primer lugar suelo trabajar muy cerca del usuario y con una estrategia de entrega continua. Al mismo tiempo, en los equipos en los que trabajo suelo ocupar un rol tipo «XP Coach» con el foco en lograr que el equipo pueda entregar software de valor, de calidad, de manera sostenible y predecible. Generalmente los equipos con los que trabajo no tienen experiencia en TDD. Típicamente trabajo en aplicaciones comúnmente denominadas como de «tipo enterprise / sistemas de información» . Generalmente me ocurre que los principales desafíos que el equipo enfrenta no vienen dados por la lógica de negocio ni el modelado del dominio sino por cuestiones «accidentales» como procesos manuales, desconocimiento/(des)control de la infraestructura, trabajo desordenado, burocracia, falta de comunicación, etc.

Es en estos contextos donde encuentro especialmente útil la propuesta de Freeman & Pryce, concretamente cuando proponen:

  • Comenzar con un walking skeleton que nos permita establecer las bases de la arquitectura de la aplicación de punta a punta.
  • Que ese walking skeleton este cubierto por una prueba de aceptación end-to-end
  • Incluir como parte de ese walking skeleton el proceso de versionado, build, test y deploy a un ambiente simil producción en un esquema de integración continua

Esto en un punto excede el estilo de TDD y por ello es me parece más preciso hablar de la propuesta de Freeman & Pryce que del estilo London cuando me refiero a estas cuestiones.

Ahora bien, una vez completo el walking skeleton entonces sí podemos hablar del estilo de TDD. Ahí la propuesta de Freeman & Pryce es comenzar «desde afuera» trabajando en el doble ciclo TDD (estilo London). Esto requiere del uso de test-doubles, posiblemente el punto más cuestionado de este enfoque. Las críticas a esta cuestión se deben principalmente al hecho de que puede resultar costoso el mantenimiento de los test-doubles a medida que la aplicación (y el diseño) van evolucionando. Coincido en que esta cuestión es un riesgo, pero en mi caso lo suelo mitigar tratando al código de tests con el mismo cuidado con el que trato al código de la aplicación y utilizando todo un conjunto de técnicas para asegurar su mantenibilidad. Muchas de estas técnicas están descriptas en el mismo libro de Freeman y Pryce, pero también hay algunas otras que he encontrando muy útiles en los libros de Gojko Adzic (Fifty Quick Ideas To Improve Your Tests, Specificacion by Example) y Gerard Meszaros (xUnit Test Patterns: Refactoring Test Code).

Una cuestión que quiero destacar de este enfoque es que me resulta muy conveniente la idea de ir diseñando/desarrollando la aplicación desde afuera porque eso nos pone en una posición de «cliente/usuario» de nuestro propio código, evitando en cierto modo la creación de métodos/comportamientos/atributos/artefactos que «el cliente» no requiera, entiendo aquí como cliente a «la capa/el objeto» que consume nuestro código y que indirectamente termina expresando la necesidad del cliente/usuario persona.

TDDeando la arquitectura

El viernes pasado estuve dando una charla titulada así en el contexto del meetup online de ArqConf.

Había más de 370 registrados pero como suele ocurrir con los meetups gratuitos, rara vez se llega al 50 %. Cuando comencé a hablar había alrededor de 120 personas y me consta que luego se fueron sumando más pero no tengo presente cuántos.

Dado que la charla trataría sobre TDD, comencé haciendo una breve encuesta a los presentes sobre su conocimiento de TDD. Si bien más del 90 % conocía TDD, tan solo el ~17 % dijo utilizarlo a diario. Personalmente no me sorprende, porque según estudios formales que hemos realizado en los últimos años, el uso consistente de TDD ronda el 20%.

La presentación fue grabada y está disponible en YouTube y los slides están disponibles aquí.

Estos son algunos de los libros en los que me basé para armar la charla:

  • Growing object-oriented software guided by tests, de Freeman
  • Designing Software Architectures: A Practical Approach, de Cervantes y Kazman
  • Just Enough Software Architecture: A Risk-driven Approach, de Fairbanks
  • Building Evolutionary Architectures: Support Constant Change, de Ford
  • Specification by example, de Adzic

Agradezco a Gus Brey y demás organizadores por la invitación.

BDD, ATDD y SBE ¿es todo lo mismo?

En la actualidad nos encontramos con estos 3 acrónimos que en muchas ocasiones son utilizados como sinónimos y cuya diferencia no es del todo clara. Más aún, en Una Mirada Ágil los mencionamos a modo informativo sin entrar en mayor detalle pues consideramos que en esencia todos apuntan a lo mismo: la importancia central del trabajo colaborativo entre técnicos y la gente del negocio para especificar la funcionalidad a construir utilizando ejemplos concretos. Y también todas ponen el aspecto colaborativo por encima del aspecto técnico (ejecución automatizada).

Personalmente creo que las principales diferencias radican en que cada uno de estos términos surgió como consecuencia de distintas líneas de trabajo que se desarrollaron en paralelo con distintos protagonistas, todos ellos trabajando principalmente desde la industria y bajo un paradigma de desarrollo ágil. Más allá de los argumentos que pueda tener cada uno de los protagonistas para insistir con su terminología creo que adicionalmente hay una cuestión natural de «orgullo» (y posiblemente también de negocio/marketing) que en cierto modo dificulta la unificación de terminología. Como suele decirse: «Cada maestro con su librito».

Más allá de esto quisiera dedicar algunas líneas a cada propuesta en particular:

Behaviour-Driven Development (BDD)

Este es el término posiblemente más utilizado en la actualidad, muy asociado a la familia de herramientas Cucumber y cuyo mayor referente es Dan North. El mismo North define BDD como:

BDD is a second-generation, outside-in, pull-based, multiple-stakeholder, multiple-scale, high-automation, agile methodology. It describes a cycle of interactions with well-defined outputs, resulting in the delivery of working, tested software that matters. 

Resalto aquí el hecho de considerar BDD una metodología lo cual es posiblemente la mayor diferencia (a nivel de marketing al menos) con las otras técnicas.

Acceptance Test-Driven Development (ATDD)

Sin duda el punto inicial de todo esto fue TDD, cuya concepción original por Kent Beck era levemente distinta a la actual. Inicialmente Beck hablaba tanto de prueba unitarias como de usuario (customer tests en términos de XP), pero con el correr del tiempo el término TDD fue tomando una connotación unitaria, o sea, en la actualidad TDD se interpreta casi exclusivamente como UTDD (Unit Test-Driven Development). De ahí la necesidad de utilizar el término ATDD para referirse explícitamente a un ciclo de más alto nivel en el cual está involucrada la gente de negocio. Una curiosidad es que Beck en su libro TDD by Example menciona ATDD, pero como acrónimo de Application Test-Driven Development en lugar de Acceptance que es el término utilizado en la actualidad.

Specification by Example (SBE)

Este es el término impulsado por Gojko Adzic y personalmente es el que más me gusta. No porque proponga algo muy distinto, sino simplemente por la terminologia que propone. En el prefacio de su libro Specification by Example Gojko propone una terminología y explica porque la terminología alternativa comúnmente utilizada no le resulta apropiada.

Finalmente no quiero dejar de mencionar que hay algunos otros términos que también suelen utilizarse como sinónimos y que en esencia son lo mismo pero cuya popularidad es mucho menor. Entre ellos se encuentran Story Test Driven Development (STDD) y Example-Driven Development (EDD).

BDD, ATDD y SBE ¿es todo lo mismo? Si.

Breve historia de las herramientas BDD – parte 2

En un artículo anterior conté una parte historia, he aquí la otra.

Mientras que Dan North y los suyos trabajaban sobre JBehave y afines que luego llevarían al surgimiento de Cucumber, Ward Cunningham trabajaba en cuestiones relacionadas a pruebas de aceptación.

El trabajo de Cunningham se tradujo concretamente en una herramienta llamada FIT: Framework for Integration Testing, cuyos objetivos pueden resumirse como:

  • Ayudar a pensar y comunicar las necesidades que debe cubrir una aplicación de software en base a ejemplos concretos de uso
  • Probar automáticamente desde una perspectiva de negocio que una aplicación de software hace lo que efectivamente se espera de ella y que continúa haciéndolo a medida que crece en funcionalidad

Para lograr esto, FIT propone escribir los ejemplos con herramientas capaces de generar HTML (Word, Excel, etc) utilizando distintos tipos de tablas para dar cierta estructura unificada a los ejemplos y facilitar así su interpretación. Una vez escritos los ejemplos trabajando en conjunto con gente de negocio y técnicos, se escribe código Java que interpreta la tablas e interactúa con la aplicación en cuestión.

El propio Ward Cunningham escribió la primera implementación FIT en Java, mientras que tiempo después James Shore tomó la coordinación general del proyecto y colaboró en la implementación en C#.

En 2005 Ward Cunningham junto con Rick Mugridge publicaron el libro Fit for Developing Software: Framework for Integrated Tests, el cual explica de forma bastante detallada el uso de FIT.

A lo largo del tiempo han ido surgiendo diversas herramientas en el ecosistema FIT, algunas de las cuales se integran con FIT mientras que otras lo extienden. Una de las más destacadas es FitNesse, desarrollada por inicialmente por Robert Martin y que en cierto modo agrega una interface de usuario por encima de FIT permitiendo que los ejemplos sean escritos en una Wiki. De esta forma FitNesse oficia de interface de usuario y FIT de motor de ejecución. Esta combinación tuvo buena recepción en la comunidad y para 2006 David Chelimsky y Mike Stockdale ya habían publicado una implementación de FIT en C#.

Fue a partir de esa implementación en C# que en 2008 Gojko Adzic publicó el excelente libro Test Drive .NET Development with FitNesse. Si bien este libro tiene un foco técnico, el autor resalta la importancia del trabajo colaborativo en entre gente de negocio y técnicos para la identificación y especificación de ejemplos. Los siguientes libros de Gojko se centraron precisamente en estas cuestiones de colaboración dejando de lado las cuestiones técnicas.

Fuentes:

¿Realmente necesitas una nueva herramienta para hacer ATDD?

Recientemente recibí una consulta por Twitter sobre este tema y dado que la respuesta no entraba en 140 caracteres decidí escribir este post.

Acceptance Test-Driven Development (ATDD) es una práctica de desarrollo ágil cuya popularidad está en franco ascenso. La idea es simple: guiar el desarrollo de funcionalidades a partir de sus correspondiente pruebas de aceptación. ¿Pero eso no es TDD? Si y no. Conceptualmente ATDD es como TDD en el sentido que es la prueba la guía el desarrollo, pero en general cuando hablamos de TDD estamos hablando del desarrollo de clases, una actividad que realiza el programador. Cuando hablamos de ATDD (o BDD o SBE) hablamos del desarrollo de funcionalidades desde la perspectiva del usuario lo cual requiere del trabajo conjunto del usuario y el programador. Resumiendo:

La principal diferencia entre ATDD y TDD pasa por el involucramiento del usuario en la definición de las pruebas que guiarán el desarrollo y la granularidad de las mismas.

Incluso, hay quienes afirman que el mayor beneficio de ATDD no pasa por la automatización de las pruebas sino por el involucramiento temprano del usuario en la definición de las pruebas de aceptación.

Habiendo dejado en claro los conceptos, vamos a las herramientas. Cuando hacemos TDD escribimos las pruebas en el mismo lenguaje que estamos programando nuestras clases y utilizamos para ello alguna herramienta de la familia xUnit.

Cuando hacemos ATDD escribimos pruebas de funcionalidades desde la perspectiva del usuario e idealmente lo hacemos trabajando en conjunto con él. Esto nos obliga utilizar alguna herramienta de especificación que resulte amena para el usuario quien generalmente no es alguien técnico. Dos herramientas muy difundidas en este terreno son Cucumber y Fitnesse, las cuales ofrecen un lenguaje de especificación muy amistoso y poco técnico. Luego tendremos que escribir lo que se denomina «glue code» para traducir las especificaciones escritas por el usuario a instrucciones ejecutables que se traduzcan en mensaje concretos a nuestro sistema bajo prueba. Este este sentido, puede que esa traducción ocurra a distintos niveles. O sea, una especificación del usuario podria terminar siendo una prueba a nivel de UI o bien una prueba a nivel de servicio o incluso una prueba a nivel de componente o clase. Esto no es un tema menor, ya que tiene un importante impacto en la elección de la herramienta a utilizar.

Si yo pretendo hacer ATDD generando pruebas de aceptación a nivel de componente/clase, entonces deberé elegir una herramienta que esté construida en el mismo lenguaje que mi aplicación. Pero si yo prefiriera hacer pruebas a nivel de UI, entonces tendré más libertad y podré elegir utilizar un lenguaje distinto para programar las pruebas. En este sentido conozco de varios proyectos en Android, .NET y Java, con pruebas de aceptación realizadas con Ruby. Debo admitir que cuando vi esto por primera vez, me resultó chocante, pero luego estuve involucrado en un par de proyectos en que se utilizaba esta estrategia y resultó muy cómodo.

La consulta que disparó este post tenia que ver con herramientas para hacer ATDD cuando la aplicación está construida en .NET. Mi respuesta concreta es:

  • Si el usuario va estar involucrado activamente en la escritura/validación de las pruebas y esas pruebas serán a nivel UI
    => Tienes muchas alternativas pues no estas atado a .Net. Básicamente cualquier herramienta de la familia Cucumber o Fitnesse estará bien.
  • Si el usuario va estar involucrado activamente en la escritura/validación de las pruebas y esas pruebas serán a un nivel por debajo de la UI
    => Puedes usar Specflow o Fitnesse (con su conector para net)
  • Si el usuario no va estar involucrado, entonces tienes libertad total y puedes escribir tus pruebas incluso con algo de la familia xUnit, ya que los únicos que leerán esas pruebas serán los técnicos, pero claro, ya no estarias contando con todos los beneficios de ATDD.

Dicho todo esto: ¿Realmente necesitas una nueva herramienta para hacer ATDD?