El desarrollo de software son conversaciones (VI)

Tiempo aproximado: 10 min.

Ya va siendo hora de retomar esta serie sobre las conversaciones en el desarrollo de software. Tal y como avancé en el capítulo IV, quiero acabar con la fase del “downstream” en este (espero) penúltimo capítulo. Así, hoy voy a hablar sobre las pruebas y el despliegue: esas actividades que solemos realizar desde que consideramos que una nueva funcionalidad está acabada, hasta que realmente está a disposición de los usuarios.


Las pruebas

No quiero hablar en este artículo de Software Quality Assurance (SQA) ni de Agile Testing porque hay mucha gente por ahí que sabe mucho más que yo de esto. Pero sí quiero concentrarme en las conversaciones que he observado que se producen en esta etapa del desarrollo. Todas ellas están íntimamente ligadas con el Criterio de Aceptación que mencioné en el capítulo III.

Acabado-acabado

Cuando hablamos de Criterio de Aceptación no puedo evitar recordar el concepto de Acabado-Acabado, que vi por primera vez en el magnífico libro de @JamesShore “The Art of Agile Development”. Si hemos dejado muy abierto el Criterio de Aceptación, será fácil que, llegados a este punto, debamos tener muchas conversaciones para acordar qué significa acabado-acabado para todos. Igual que habrá sucedido mientras programabamos. Si hay dudas, hay que aclararlas. Al fin y al cabo, los agilistas creemos que:

El método más eficiente y efectivo de comunicar información al equipo de desarrollo y entre sus miembros es la conversación cara a cara.

Sin embargo, me gustaría acotar un poco las conversaciones en función del punto del proceso de construcción y despliegue de la pieza de software en el que nos encontremos.

Pruebas antes de acabar la programación

Antes de que una historia de usuario la consideremos acabada-acabada, realizamos muchas pruebas. Las que hemos desarrollado durante la programación de esa funcionalidad las considero como parte de esa actividad. Me refiero tanto a las de arriba como a las de abajo de la famosa pirámide del testing de Fowler porque, en mi opinión, una funcionalidad no la deberíamos considerar acabada hasta que no podamos integrarla con el resto del producto.

En ese sentido, siempre aconsejo, por ejemplo cuando hacemos Kanban, que la tarjeta no avance hasta que el nivel de acabado de esa pieza no sea el acordado, es decir, hasta que las pruebas unitarias, de integración de componentes, y de aceptación (de UI y/o de servicio) estén todas automatizadas, y poniendo en verde nuestro sistema de integración continua.

Ojo, en algunos casos, seguir esta recomendación puede implicar forzar mucho la situación. No todas las organizaciones están siempre en condiciones de seguir la receta ideal.

Pruebas antes de empezar el despliegue

En muchos contextos, tener acabada la programación no significa que pongamos la funcionalidad inmediatamente en la calle (lo que llamamos el despliegue). A veces estamos en entornos complicados, con otros equipos trabajando a la vez que nosotros en el mismo monolito, por ejemplo, y necesitamos sincronizarnos con ellos para desplegar e incluso comprobar que, ni nosotros hemos estropeado algo que otros han hecho, ni viceversa.

A estas pruebas yo he oído llamarlas con diferentes nombres: pruebas de integración, pruebas funcionales, UAT, pruebas end-to-end, etc. Lo importante aquí no es tanto el nombre como la intención, y que podamos ponernos de acuerdo en qué significa para todos los que colaboramos en el desarrollo de esa pieza de software que una prueba está en verde, y cómo vamos a actuar si no lo está.

A medida que se acerca el final del proceso de desarrollo, los acuerdos de trabajo son más y más críticos, porque además son más susceptibles de ser automatizados, y ser explícitos en los acuerdos de trabajo es el mejor camino para su automatización.

Tren de releases

En entornos con muchos componentes a integrar por parte de muy diferentes equipos es frecuente sincronizar las entregas con un tren de releases (metáfora de la que ya he hablado en su momento en este blog).

Desde el punto de vista de las conversaciones, el tren de releases es muy rico para reflexionar sobre cuáles deben ser las mejoras en nuestros procesos: “No deberíamos correr para alcanzar ese tren porque es más fácil tropezarnos y no llegar a tiempo, o llegar sudando, o con la maleta medio vacía…”, “Si el tren viniera más frecuentemente no tendríamos que correr”“Si tuviéramos pronto todo lo importante en la maleta, que llegara el tren no sería tan crítico”, etc.

También es un mecanismo muy bueno para llegar a acuerdos y reducir los conflictos entre equipos y departamentos con diferentes objetivos.

Conversaciones no automatizadas

La automatización de las pruebas ayuda a tener las conversaciones sobre si algo está acabado-acabado mucho antes y también a que los debates sean más objetivos, pues nos centraremos siempre en qué significa que el test está en verde y/o en rojo.

En mi experiencia, es bueno buscar expertos en este terreno si no se tienen en el equipo, pues es fácil caer en la trampa de que, si tengo todas las pruebas automatizadas en verde, mi producto hace lo que espero.

El testing exploratorio es una actividad realizada por humanos (al menos de momento) que ayuda a cubrir este hueco. Esta actividad se realiza en base a heurísticas y con un método, por tanto, las conversaciones que tengamos con los expertos serán muy importantes para aumentar la calidad de nuestro producto y nuestros procesos.

Pero no todo el monte es orégano y es fácil encontrarse en un contexto donde la mayoría de las pruebas no están automatizadas. Así pues, tendremos que ser conscientes de la importancia vital que tendrán las conversaciones entre quienes ejecutan esas pruebas y quienes han construido el software.

Tener procesos está bien, incluso ordenar el resultado de la ejecución de las pruebas para procesarlas de una manera más eficiente, y también está bien tener planes de ejecución de esas pruebas. Pero no deberíamos olvidar que todos ellos son resultado de una disfunción en nuestro proceso de construcción, que nos está obligando a gestionar un gran volumen de trabajo manual. Cuanto antes automaticemos, antes podremos salir de ese pozo.

Cuando la mayoría de las pruebas que se realizan están automatizadas, entonces las conversaciones tienen que ver, o bien con la definición y ejecución de las pruebas manuales, o bien con los errores que se encuentran durante la ejecución de las pruebas (ya sean automáticas o manuales). Ésas sí son conversaciones de valor pues se centran en el producto de una manera objetiva ya que los escenarios en los que se produce un defecto, o una discrepancia en la interpretación de la funcionalidad, son reproducibles.

Usar lenguajes tipo Gherkin y patrones tipo Given/When/Then creo que son buenas prácticas que ayudan mucho a este objetivo de compartir el Criterio de Aceptación entre todos los roles del equipo. De paso tendremos la documentación interna de nuestro producto automatizada y ejecutable.

UAT

Finalmente, hay un tipo de prueba manual que llamamos UAT (User Acceptance Test) o prueba de aceptación, a la que quiero dedicar especial atención pues suele ser una intensa fuente de conflictos.

Es fácil que un equipo que trabaja con iteraciones, p.ej. haciendo Scrum, decida que la UAT se hace durante el Sprint Review. También es fácil que el Sprint Review se convierta en un chequeo superficial del criterio de aceptación y que dejen para después la UAT, como parte del trabajo a realizar durante la integración en un tren de releases, por ejemplo. Incluso también he visto hacer la UAT en producción. Pues bien, ninguna de ellas está bien ni mal, pues depende mucho de si el equipo es consciente de para qué está haciéndolo de esa manera y qué está dejando de hacer en cada caso.

Si empleamos el Sprint Review para hacer la UAT, seguramente será porque tenemos pocas funcionalidades que revisar y queremos estar todos en la conversación. Sin embargo, es fácil que se convierta así en una reunión muy aburrida y que, por cierto, se olvide el objetivo de esa reunión, que es revisar qué se ha entregado durante esa iteración, qué ha quedado en curso y qué podemos aprender de ello.

Si consideramos que la UAT es hacer un repaso somero del criterio de aceptación nos estaremos olvidando quizás de esos casos raros que nos encontrarán los usuarios en producción y que aumentarán el coste de desarrollo, como bien sabemos, pero si en este caso, en vez de llamarlo UAT lo llamamos comprobación del criterio de aceptación antes de la integración, y lo ejecuta el dueño de producto (o idealmente un usuario), y podemos obtener su feedback temprano, podemos evitar el coste de llevar a producción una funcionalidad defectuosa.

Hacer una UAT en producción sólo tiene el inconveniente de que ya está en producción, por lo que en realidad la estamos haciendo para obtener feedback del dueño de producto, por ejemplo, o para comprobar que las métricas están funcionando como esperábamos en nuestra hipótesis. (Recuerda que en el capítulo I hablabamos de que todas estas conversaciones pueden ser originadas por la necesidad de validar o refutar una hipótesis).

Todas estas conversaciones se pueden facilitar con plantillas como la Test Card o la Learning Card. En mi opinión, la Test Card es un magnífico recordatorio de por qué estamos haciendo esa funcionalidad y cómo vamos a comprobar si funciona o no cuando la despleguemos. Hablaré de ambas en el siguiente capítulo, dedicado al feedback, en el que también hablaremos de algo llamado A/B testing, que yo no considero exactamente una prueba (en el sentido en el que lo estamos considerando en este capítulo).

Despliegue

Pruebas en producción

Antes de desplegar debemos asegurarnos de que el nuevo desarrollo no estropea nada de lo ya existente en producción. A esta ejecución de pruebas de regresión algunos la llaman “sanity”. La mayoría deberían estar automatizadas, pero no siempre es posible. Lo más importante no es tanto la ejecución de las mismas, que lo es porque debemos ser exhaustivos (al menos en las funcionalidades críticas de nuestro producto), sino cómo actuar frente a los defectos y/o desacuerdos que se producen.

De nuevo, un buen criterio de aceptación en cada historia de usuario es esencial, y el plan de pruebas de regresión no es más que una “demo” de historias de usuario que se escribieron hace mucho tiempo y que tienen un gran valor pues debemos asegurarnos de que siguen funcionando después de cada integración. Las conversaciones que dieron lugar a ese desarrollo tuvieron lugar hace tanto tiempo, que es imprescindible dejar constancia por escrito de qué hay que comprobar en cada caso. Lógicamente, mucho mejor si lo puede comprobar una máquina.

El tren de releases y la entrega continua

Ya he hablado más arriba del tren de releases como una práctica para reducir conflictos en entornos donde no se tiene completa autonomía para desplegar un desarrollo una vez consideramos que está acabado-acabado. En cualquier caso, el tren de releases señala una ineficiencia en nuestro proceso pues impide que una funcionalidad ya acabada pueda ser desplegada inmediatamente y deba esperar “a que llegue el tren”. Medir este proceso (cúanto tiempo está esperando una funcionalidad desde que está acabada hasta que puede ser desplegada, por ejemplo) ayuda a darle la justa importancia a las mejoras que podamos hacer en esta parte del proceso.

La mayoría de estas conversaciones se simplifican, una vez más, cuando estamos en un entorno donde hemos conseguido la entrega o el despliegue continuos. Hemos debido tener las conversaciones durante el proceso que nos ha llevado a automatizar todos esos procesos. Lo demás es ajustar.

Es fácil que queramos ir reduciendo el tiempo que una funcionalidad tarda en ser desarrollada pero que luego se quede esperando mucho tiempo “a que llegue el tren” o que nuestro proceso para ponerla en producción sea especialmente lento o falto de calidad. Nuestras conversaciones aquí deben estar destinadas a hacer objetivo dónde poner el foco. Las métricas nos ayudarán mucho y reuniones tipo Service Delivery Review son el foro adecuado para tener estas conversaciones.

A/B testing

Aunque ya hablaré en el capítulo siguiente sobre los A/B y su relación con el feedback, aquí creo que debemos comentar que un A/B es una funcionalidad que, al menos durante un tiempo, convive con la funcionalidad a la que pretende sustituir con el objetivo de comparar su rendimiento de negocio. Para ello, de nuevo, no sólo es importante lo que hayamos acordado al principio del proceso sino también lo que hayamos ido hablando durante el mismo. Llegados a este punto, si no teníamos claro que la funcionalidad iba a convivir con otra, podría ser imposible desplegarla.

DevOps

¿Ah? ¿Que no he mencionado el término DevOps? Juro que tengo un poco de reparo a tratar este asunto porque se ha convertido en un asunto polémico, pero creo que es necesario porque esta serie de artículos se centran en las conversaciones y, por tanto, en la colaboración entre roles. Así que, por parapetarme un poco para empezar, usaré la definición que he encontrado con la que me siento más cómodo. Ésta de Atlassian. (Perdón si la traducción no es del todo buena. Se aceptan comentarios).

DevOps es un conjunto de prácticas que automatizan los procesos entre el desarrollo de software y los equipos de IT, de manera que puedan construir, probar y entregar software más rápido y con más fiabilidad. El concepto de DevOps se basa en construir una cultura de colaboración entre equipos que históricamente funcionaron como silos entre ellos. Los beneficios prometidos incluyen incremento de confianza, entregas de software más rápidas, capacidad para resolver incidencias críticas rápidamente, y una mejor gestión del trabajo no planificado. (…) Es un firme acuerdo entre desarrollo y operaciones que enfatiza un cambio en mentalidad, mejor colaboración e integración más ajustada. Forma una alianza entre Agile, entrega continua (continuous delivery), automatización y mucho más, para ayudar a los equipos de desarrollo y operaciones a ser más eficientes, a innovar más rápido y a entregar más valor al negocio y a los clientes.

Decía que ésta es la definición que he encontrado con la que me siento más cómodo porque es donde se hace más énfasis sobre los aspectos colaborativos, no sólo de la automatización de los procesos interdependientes. Y también porque se menciona el valor entregado al negocio y a los clientes. Por tanto, se trata de una cultura de colaboración que toca desde el principio hasta el final de la cadena de valor. Desgraciadamente, la industria lo está malinterpretando como “un departamento de sistemas (o de operaciones), pero ágil” y vemos ofertas de empleo que ofreciendo puestos de devops, cuando en realidad quieren decir que sea capaz de automatizar las tareas de pruebas y despliegues que los programadores no saben (o quieren) hacer.

Ea. Ya me he mojado.


En el capítulo que viene acaberemos esta serie hablando del feedback. Hablando de ello, si me quieres dejar tu feedback, ahí abajo hay una caja para dejar tu comentario. Tu opinión siempre es bienvenida.