Cómo empezar a implementar una cultura de testing

Este post no es una guía de testing, ni tan siquiera un plan de cómo se debería introducir una orientación a testing en un equipo de desarrollo, NO está pensado para las grandes organizaciones maduras y que llevan años haciendo TDD de «categoría». Más bien son una serie de pinceladas donde nos gustaría mostrar nuestra posición respecto de la cultura del desarrollo orientado a test desde un punto de vista práctico y realista.

Ten claro que es testing

Testing NO se trata de buscar o encontrar bugs, se trata de evitar CREAR dichos bugs, tanto en código, como en arquitectura, como en la parte de UX, etcétera.

Esto responde a un modelo muy «lean»: evitar el desperdicio, básicamente se trata de escribir un código que NO genere bugs, porque si es así, haremos doble trabajo:

Esto como es obvio, no es muy eficiente.

    • Escribir el código (aquí escribimos el bug)
    • Testeamos (buscamos el bug)
    • Intentamos solucionar dicho bug
    • A veces lo conseguimos, pero solo tenemos claro lo relativo a «este bug» y no es un modelo extendido a todo el desarrollo , por tanto tendremos más bugs, más pruebas de regresión, más pruebas de…..

Es bastante más sencillo y productivo hacer esto:

    • Escribimos el test
    • Escribimos el código
    • Automatizamos el test
    • Si pasa el test no tendremos bug (en teoría)
    • Si después hay bugs sabremos dónde buscarlo (o en el propio test o en el código)
    • Si no lo encontramos, sabremos dónde buscar o no buscar (test y código)

Si haces «testing» aumentarás la calidad y acumularás menor deuda técnica

«Hacer testing» nos ayuda a tener mayor calidad y menor deuda técnica, en el ejemplo anterior se puede ver de manera obvia, además al escribir test entenderemos mejor nuestro código y detectaremos con mayor rapidez sus puntos débiles y por dónde puede fallar.

Esto como es lógico nos lleva a una situación de partida donde inicialmente se desarrolla con menos velocidad (además de escribirlos conviene recordar que los tests también se deben de mantener) pero, al contrario de un modelo clásico o donde no exista la cultura del testing, conforme el desarrollo aumenta (en complejidad, en tamaño, etc) y conforme el negocio va cambiando y evolucionando la velocidad será mayor dado que no «arrastras» un código problemático (curvas «J»).


Empezar poco a poco

No intentar pasar de cero a cien. Introducir una cultura de test en un equipo de desarrollo (o empresa) no es sencillo ni rápido, vale la pena ir despacio pero cada paso que esté bien asentado, por ejemplo:

  • Empieza con pequeños test unitarios, un test unitario solo debería testear «una cosa», hazlos sencillos y «cortos», ya publicamos hace tiempo un tweet con las conclusiones de google respecto a el tamaño de los tests Testing.googleblog.com
  • No busques cobertura al 100%, y al principio ni siquiera un 20%, centra tu esfuerzo y tu tiempo en buscar dónde está tu problema principal: esa parte «intesteable» o donde más bugs te genera (acoplamientos, comunicaciones entre módulos, clases extensas y complejas, herencias «imposibles», código legacy, partes y comportamientos «ocultos», etcétera) y piensa en «trocear» de manera pequeña y sencilla tus tests, acuérdate del concepto unitario y de que los test se deben de mantener.
  • Automatiza desde el primer día (o casi) tus test, está muy bien tener un código testeado y testeable, pero si no se lleva a una automatización de dichos test (e insisto; los test se deben mantener) el problema será que al final (o casi al principio, eso depende de quien tome decisiones) no se testeará y te los «saltarás», esto es bastante más común de lo que parece y como es obvio te lleva a NO testear, y más vale pocos test sencillos y mantenibles que ninguno.
  • Cuando automatices, hazlo sencillo, manejable y mantenible, más vale que se empiece por algo sencillo como pueda ser pasar un estándar (por ejemplo PSR para php) y medir la complejidad ciclomática, pero que se haga en cada commit que no intentar aprovechar el 100% de selenium o Appium pero que dichos test sean «grandes», completamente manuales y que no se puedan mantener.
    Plantearlo como un proyecto sin fin (mientras el software tenga vida, esto del testing e ir «metiendo» cosas nuevas y aumentado la calidad y la cultura y orientación al test debería estar «vivo») y con su propio MVP, sprint, retrospectivas, etcétera.
    Si ese test que (por continuar con el ejemplo) usa selenium es necesario y está hecho pero no lo has podido automatizar, prioriza, piensa en tu backlog (de test sin automatizar o que necesitan refactoring, etc) hazte una history mapping o lo que quieras pero no aumentes la deuda técnica del testing (o acabarás pasando de ellos -> de los tests) y sobre todo no automatices lo que no tengas bien claro que te ayuda, da valor y es necesario (de nuevo principios Lean).
    Date tiempo, piensa y sobre todo evalúa si dicho test realmente debe ser así de «extenso y/o complejo» o por el contrario lo puedes «trocear» (volvemos al punto de antes: concepto unitario, etc,,,más que hacia epics 🙂 y realmente es importante y te aporta valor.

El testing NO es exclusivo de desarrollo, todo el negocio debe estar implicado

Este punto es sencillo y rápido de explicar: si no se consigue que toda la organización piense en mejorar la calidad del software y esta se queda únicamente «en el tejado» del equipo de desarrollo es casi seguro que nunca se llegará a un mínimo de calidad.

Un buen principio lo encontramos a la hora de redactar pruebas de aceptación en las historias de usuario o los items (si se prefiere otra cosa que no sea SCRUM), si la organización se vuelca en pensar que deberá testear (en este caso es tal cual una prueba de aceptación) esa cultura de estar anticipándose a los problemas e intentar ya no solucionarlos, sino NO crearlos, se asentará.

El mismo ejemplo lo podemos encontrar cuando se reporta un bug por las personas que no son técnicas, si esas personas entienden la importancia de reportar de manera adecuada, si se plantea como un trabajo común donde el usuario participa de manera activa y no pasiva es muy probable que a la hora de redactar nuevos o existentes test el foco esté mucho más claro y por tanto se testee lo que realmente aporta valor al negocio.


Piensa en el código

Separa el código de los test

Esto es bastante obvio pero (y hablamos por propia experiencia de nuestro código) muchas veces simplemente se usa un directorio donde pone «test» y allí queda, es cierto que frameworks como lenguaje_x_unit facilitan muchísimo la labor al tener sintaxis muy sencillas de entender, pero si te reproduces exactamente la estructura de directorios y piensas en la arquitectura que estas usando (para añadir) después todo sera más sencillo, incluso puedes plantearte tus propias métricas y modelos de calidad y cobertura en este sentido.
Además esto te será de muchísima utilidad para, por un lado si logras introducir un modelo de colaboración de todo tu negocio (lo que hablamos en el bloque anterior) dado que la integración de dicho modelo la tendrás separada del código.

Por otro cuando empieces a usar «objetos de imitación» (me refiero a dummys, fakes, mocks y stubs principalmente) podrás separarlos y aislar el uso de estos, es decir: Digamos que un mock ayuda a encontrar el problema en las integraciones (con problemas de acoplamiento… imaginaros) y un stub nos ayuda a comprobar que una cosa funciona como se espera (valores, por poner un ejemplo) por tanto cuando tu proyecto y tu código crezcan el tener aislado y separado esto te será de muchísima utilidad, además, piensa que esto funcionará en nuestro entorno, pero OJO que cuando salimos de él la cosa puede fallar y si tenemos muy acoplado el modelo podremos tener los consabidos problemas de mantenibilidad, etcétera.

No olvides los principios básicos

Si eres capaz de escribir bien, algo tan sencillo como un nombre de una clase, de variables, constantes y ficheros/directorios, ya tendrás código más fácilmente testeable. Es cierto que esto pertenece a las recomendaciones más básicas y simples para escribir código pero la idea es que se cumpla a rajatabla, desde un simple jenkins con sonarqube ya puedes automatizar esto, que si bien es simple es extremadamente útil, en este caso cuando escribes los test te ayudará mucho a entender de manera funcional (me estoy refiriendo al comportamiento) que hace tu código, su nivel de complejidad, sus puntos flacos y por tanto donde debes poner énfasis y esfuerzos para testear.

Usa patrones (o lo que quieras) para evitar sobre todo el acoplamiento (los principios de builder suelen ir bastante bien para «ensamblar» tus test), cuando tengas grandes baterías de tests el acoplamiento puede ser un problema, generalmente usarás algún framework como lenguaje_x_unit, también es probable que uses mockitopowermock o algún otro mocking framework por lo que esto se tornará aún más importante.


No todo es testeo unitario

Aunque pensamos que la base de todo buen sistema y por ende la cultura del testing debe estar asentada en dos principios:

    • A)Testeo unitario
    • B)Automatización

Es cierto que en una buena cultura de testing no deberíamos centrarnos únicamente en testeo de bajo nivel y olvidar por tanto las pruebas de integración, las de carga, las de regresión, de estrés, de sistema, funcionales, aceptación, etcétera.

Lo que nos ha funcionado muy bien es crear relaciones entre ellas e incluirlas en una cultura y un plan general para orientar a las organizaciones/equipos/etc hacia la calidad.

¿Cómo conseguirlo? Es algo más complejo y en cada equipo puede funcionar una cosa y otra no, pero lo que sí que nos está funcionando razonablemente bien es, sobre todo, un buen control de los propios bugs:

    • Lleva un control de tus commits, tus sprints y tus items del backlog que tengan alguna relación con tus bugs (fechas, usuarios, quién pide, áreas funcionales de tu software, o lo que se te ocurra).
    • Si además tus bugs están bien «alimentados» aun lo tendrás más sencillo, tanto a la hora de «encontrarlos» como de solucionarlos, se trata de incluir información relevante y de calidad en dichos bugs para que puedan ayudarte a afinar mejor la dirección de tus test (por ejemplo incluye plataformas, o tipo de datos, etcétera).
    • No le dejes el trabajo de manera exclusiva al equipo de desarrollo, ya lo comentábamos antes, el testing no es algo exclusivo de desarrollo, intenta que en las descripciones de los bugs se explique qué se pretendía hacer y para qué, si esto lo tienes enlazado de alguna manera y tienes algo tan básico como el código bien escrito será muchísimo más fácil escribir ese nuevo test.

No te olvides de los testeos «clásicos» como el branch testing, te ayudarán y mucho a saber por dónde deberías modificar, afinar, cambiar, eliminar o añadir «cosas» a tu estrategia de testing.

Las métricas de testing, están muy bien, pero úsalas con cuidado y céntrate mucho más en las métricas de negocio, las gráficas burndown, qué estás metiendo en el backlog y qué queda, el WIP y en general los indicadores que te aportan valor y te ayudan a percibir la calidad de tu producto que únicamente en code smells (aunque no los pierdas de vista).


Por último planteate que esto es un cambio continuo, que es mejor construir con base sólida una cultura de testing para toda la organización que no tener las últimas siglas y frameworks de moda pero al final cuando «aprieta» nadie usa o quiere usar.

El testing se debe percibir desde el primer momento como algo que aporta valor al negocio, como algo básico en un equipo de desarrollo (hoy en día a nadie se le ocurre no tener un repositorio o un IDE) y nunca como algo accesorio o que de lo que se pueda prescindir.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *