Test Driven Development: Eliminando Malentendidos

Últimamente cuando alguien me pregunta por TDD acabo planteándome la misma pregunta:

¿Están interesados en la metodología de desarrollo llamada Test Driven Development o en realidad tan solo están pensando en codificar unos tests antes del desarrollo?

Parece una pregunta redundante ¿acaso no es lo mismo aplicar TDD que codificar tests antes del desarrollo de la funcionalidad?

Esta es precisamente la raíz de muchos malentendidos y la respuesta es un rotundo NO.

La Raíz de los Malentendidos

Cuando se habla de TDD en realidad muchas veces se está pensando en técnicas para  la automatización de tests de alto nivel (integración, sistema o interfaz de usuario). El interés que despierta TDD es el interés hacia las técnicas para la programación de tests automáticos, reduciendo TDD a un nombre de moda que aconseja programar los tests antes de escribir una sola línea de código funcional – lo que deja de lado aspectos fundamentales de Test Driven Development, que en realidad es una metodología con reglas propias.

Quizás el problema se deba a que la primera letra ‘T’ dirige el foco hacia el testing en lugar dirigirlo hacia la última letra ‘D’ del development (designing/coding).

Se confunde una metodología del equipo de desarrollo con una metodología del equipo de control de calidad (quality assurance).

Malentendido comprensible al formar parte del nombre de la metodología – esperemos que el cambio de vocabulario propuesto por Behaviour Driven Development con la eliminación de la palabra «test» evite este malentendido.

Test Driven Development es precisamente una metodología diseñada como herramienta de trabajo para los programadores.

No se trata de una metodología para el equipo de QA. Existen otras prácticas más directamente relacionadas con la QA como ATDD – además de prácticas específicas de Agile Testing.

Una Novedad con Mucho Retraso

Es inquietante descubrir que la “novedad” que despierta el interés parece ser la posibilidad de automatizar la tradicional fase de pruebas del sistema. No es alentador pensar que ésta es la principal inquietud, teniendo en cuenta que la programación de tests se lleva practicando desde mucho antes del nacimiento de TDD o de XP. 

MALENTENDIDO: TDD es tan sólo una recomendación que propone automatizar las pruebas de sistema mediante la codificación adelantada de los tests.

REALIDAD: TDD no es un sustituto automatizado de las actividades de pruebas de sistema ni de las actividades de un grupo de calidad.

Los programadores que participan en proyectos con recursos específicamente dedicados a la codificación de pruebas o simuladores, suelen dudar (con razón) de que el simple hecho de codificar los tests por adelantado realmente solucione problemas del testing automatizado.

La programación de tests no es una novedad y se lleva practicando desde antes de que existiera Test Driven Development o Extreme Programming.

TDD no estaría aportando nada realmente diferenciador al panorama de la codificación de tests si consistiera en una simple recomendación de programar las pruebas por adelantado.

Si la inquietud principal reside en las técnicas de codificación de tests, estamos llegando a TDD con un retraso bastante preocupante:

Test Driven Development nació en el año 1996.

Esta metodología de desarrollo se originó a partir de la experiencia de equipos que ya practicaban la codificación de tests automáticos.

Kent Beck – creador de XP y TDD – en su libro «Test Driven Development: By Example« cuenta como TDD surgió en respuesta a la necesidad de conseguir el famoso «Rapid Feedback» de XP.

La batería de tests de sistema o integración acababa requiriendo horas de ejecución, los famosos Nightly Builds (que nada tiene que ver con Continuous Integration). Los errores no eran detectados hasta el día siguiente. El feedback que proporcionan los resultados de los tests llegaban con retraso, lo que penalizaba enormemente el margen de reacción y el tiempo de corrección.

Esto hace pensar en aquellas historias sobre el trabajo con tarjetas perforadas, cuando tardaban un día en compilar y detectar simples errores sintácticos.

Surge la necesidad de un testing con un feedback más inmediato, que permita verificar minuto a minuto el resultado de los tests, para reaccionar en el momento mismo en el que se introducen los fallos.

Una sistemática en la que el fallo en un test tan sólo implique la revisión de las modificaciones realizadas en los últimos cinco minutos o últimas diez modificaciones.

Si a este método se le suma la capacidad que proporcionan estos microtests para decir como se diseña y se codifica – refactorización – entonces obtenemos Test Driven Development.

Un Bucle Iterativo e Incremental

En el siguiente artículo «Introduction to Test Driven Design (TDD)» aparece una clasificación que explica el verdadero valor diferencial que introduce TDD.

    • Test After Development (TAD)
    • Test First Development (TFD)
    • Test Driven Development (TDD)

MALENTENDIDO:  Confundir Test Driven Development (TDD) con Test First Development (TFD).

Codificar los tests antes de la funcionalidad sería Test First Development (TFD), práctica que ya se contemplaba desde antes de pensar en TDD (a veces con equipos dedicados a la codificación de dichos tests).

MALENTENDIDO:  Codificar Unit Tests por adelantado – usando herramientas tipo xUnit – es suficiente para decir que usamos TDD.

Bucle TDDTest Driven Development consiste en la aplicación iterativa e incremental de los pasos de un bucle TDD.

Cada iteración del bucle debe suponer un microincremento de tests y de funcionalidad.

Cada incremento debe consistir como mucho en unas diez modificaciones en el código.

Esta forma de trabajar implica una iteración completa cada 2 o 5 minutos, lo que supone que en una jornada de programación TDD se habrán ejecutado los tests entre 90 y 200 veces.

En su libro Kent Beck muestra datos empíricos del numero de veces que se ejecutan los test en una jornada de programación TDD.

Teniendo en cuenta que para avanzar en el desarrollo se deben ejecutar todos los tests unitarios cada dos o cinco minutos, éstos deben cumplir unas características muy concretas, conocidas como propiedades FIRST (Fast, Independent, Repeatable, Small, Transparent).

El requisito de cumplir las propiedades FIRST en los test utilizados en TDD marcan una diferencia fundamental respecto a otras técnicas de automatización de pruebas.

Una Refactorización Continua

El protagonista principal de TDD es la refactorización. El código se refactoriza continuamente en cada vuelta del bucle, lo que supone entre 90 y 200 refactorizaciones al día.

MALENTENDIDO: La refactorización se aplaza para los momentos de tranquilidad.

REALIDAD: Esos momentos de tranquilidad nunca existen.  La refactorización que se deja para luego nunca se realiza.

La refactorización es lo que realmente confiere a TDD su carácter de Desarrollo Dirigido desde las Pruebas. Los test protegen el código para permitir la refactorización, que a su vez es lo que hace emerger un diseño y una arquitectura directamente desde el código.

Resumiendo Test Driven Development

Test Driven Development = Test First Development + Refactorización

NO EXISTE TDD SI NO HAY UNA REFACTORIZACIÓN CONTINUA

Test Driven Development es una Metodología de Desarrollo y no una metodología de pruebas y calidad.

Es una herramienta para el programador, el cual escribe unos tests de los que es propietario, y que dirigen la codificación de la funcionalidad. La metodología TDD es propiedad del programador.

El equipo de pruebas no utiliza TDD, cuenta con otras herramientas más apropiadas, como por ejemplo Acceptance Test Driven Development (ATDD).

El impacto de TDD sobre la mejora de la calidad es casi un efecto lateral, ya que mediante su desarrollo iterativo e incremental a través de la codificación de Small Scaled Tests proporciona una alta cobertura de test unitarios imposible de conseguir de otra forma.

Uncle Bob lo explica de esta forma:

The act of writing a unit test is more an act of design than of verification. It is also more an act of documentation than of verification. The act of writing a unit test closes a remarkable number of feedback loops, the least of which is the one pertaining to verification of function.

— Robert C. Martin

No me cabe duda que este intento por explicar lo que no es TDD, implica que la siguiente tarea será explicar lo que sí es TDD. Pero eso lo dejaré para un «Test Driven Development: Eliminando Malentendidos II» (espero no retrasarlo mucho).

Deja una respuesta

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Salir /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Salir /  Cambiar )

Conectando a %s