Hace tiempo que trabajo en testing de performance, y ya varios años que me ha tocado participar en proyectos donde se implementa Continuous Integration y Continuous Delivery. Tuve la suerte de poder participar en un proyecto para un cliente con una realidad bastante exigente en cuanto a requerimientos de performance, y donde implementaban CI/CD incluyendo pruebas de performance en su pipeline. En particular algo bien interesante en esto, es que uno no está ejecutando pruebas de carga en cada nuevo build, no estamos simulando la carga esperada del sistema, sino que a las pruebas de performance en el pipeline le ponemos otro foco. El foco en este caso está en detectar degradaciones de performance lo antes posible. Apuntamos a feedback inmediato y a bajo costo (ejecutar una prueba de carga que simule la realidad esperada es cara ya que se requiere contar con infraestructura similar a la de producción y de acceso exclusivo, lo cual no sería fácil tenerlo para cada momento en que se quiera hacer un build en un enfoque de CI/CD). ¿Cómo logramos esto entonces? pues ejecutando pruebas más puntuales, fijas, de menor carga, pero que siempre hagan una misma validación, revisando que los resultados no tengan desviaciones que hagan que se “pierda” performance.
Para protocolos abiertos como HTTP/S existen cientos de herramientas. Una de las más utilizadas es JMeter, ya que cuenta con una gran popularidad, la comunidad Apache le da respaldo, y además de HTTP soporta una gran variedad de protocolos. El hecho de que herramientas como BlazeMeter, Visual Studio Team Services, Soasta, y tantas más, de las que ejecutan las pruebas de performance desde el Cloud, la utilicen como formato de prueba, convierte a JMeter en el estándar de facto para las pruebas de performance. Desde mi punto de vista el punto flojo de esta herramienta es que el lenguaje que brinda para automatizar es un lenguaje gráfico, lo cual no es lo más deseado para los programadores. Además, como este lenguaje gráfico se guarda en un formato xml, esto no lo hace CI/CD-friendly, ya que si quiero ver los cambios entre una versión y otra, mirar las diferencias del xml no va a resultar nada práctico.
Es por esto que herramientas como Gatling son de mi preferencia para este tipo de pruebas integradas a nuestro motor de integración continua, ya que las pruebas se programan en código (en este caso, en el lenguaje Scala). Otra opción, y creo que más alineada al desarrollador moderno que le gusta programar en un editor de texto minimalista y de fondo negro, es utilizar Taurus. Taurus es una herramienta opensource desarrollada por Blazemeter, que permite especificar las pruebas de performance en formato yml, en archivos de textos bien simples (¡en este mismo blog Aritz ya ha hablado de Taurus!). Esta herramienta solo sirve para especificar el script, y luego para ejecutarlo lo que hace es convertirlo a un script JMeter (o a alguna de las 8 o 9 herramientas con las que es compatible), logrando recolectar los resultados y generando una interfaz gráfica liviana (a diferencia de JMeter) para ver los resultados en vivo, así como también enviando los datos a BlazeMeter para poder contar con un reporte HTML en vivo, el cual realmente queda muy bien (y para usarlo no necesitamos pagar nada, es más, ni siquiera necesitamos tener una cuenta en BlazeMeter).
Al trabajar con Taurus, en este enfoque de CI/CD, hay un “truco” que a mi ver es bien fácil de implementar y que da muy buen resultado. Básicamente, la idea es dividir todo el archivo yml de Taurus en tres archivos:
- Uno con el flujo que estamos simulando, o sea, el caso de prueba, la secuencia de requests.
- Otro para la especificación del escenario, o sea, qué carga queremos simular, cuántos threads, etc.
- Y por último, uno donde indiquemos cuáles son los criterios de aceptación.
Aquí puedes ver un ejemplo:
Así tendremos tres archivos que nos permitirán ejecutar la prueba con el siguiente comando
bzt runner.yml criteria.yml load.yml
En este proyecto en Github tengo un ejemplo súper básico, pero que muestra esta idea de dividir los scripts, y puedes ver cómo organizarlos: https://github.com/fltoledo/taurus_simplest_example
Lo que nos permite esto es lo siguiente:
- Facilitar la lectura, entendimiento y mantenibilidad de las pruebas.
- Utilizar el mismo script (flujo, caso de prueba) en distintos ambientes, donde quizá lo que cambia es la carga que le quiero ejecutar, y así también los criterios de aceptación.
Con respecto a este segundo punto, creo que es fundamental poder utilizar el mismo script de pruebas, y tener distintos archivos que especifique distintas cargas y criterios de aceptación. Por ejemplo, en el ambiente de test quiero ejecutar una carga bien chica y puntual, pero en staging me interesa ejecutar una carga mayor, ya que el hardware es más similar a producción, y así los criterios de aceptación serán más exigentes también.
Otro aspecto que considero que es importante, está relacionado a qué métricas definirán los criterios de aceptación. Acá lo que tengo para aportar es lo siguiente:
- Revisar robustez, verificando que no haya más de un 1% de errores (1 o lo que se defina como aceptable).
- Revisar los tiempos de respuesta en base a algún percentil, ¡nunca promedios!
- Revisar que el throughput no baje, ya que esto también sería un indicio de que la performance se reduce.
También será importante definir la carga a ejecutar, y esto lo dejé explicado en este post que te invito a leer aquí.
Por último, considero beneficioso tener el código de pruebas en el mismo repositorio de código que el sistema, en un folder específico, pero lo importante es que me facilite la trazabilidad entre las pruebas y lo probado.
Resumiendo (TL;DR), creo que Taurus es una excelente herramienta para integrar pruebas de performance a nuestro pipeline, obteniendo así feedback temprano sobre la calidad de los cambios que se van introduciendo al sistema, específicamente en cuanto a velocidad. Para lograrlo en forma efectiva, te compartí por aquí algunos trucos que he ido recolectando en estos últimos años en diversos proyectos, y me gustaría también que me compartas tus experiencias al respecto. Puedes hacerlo en este post, en mi blog en esta entrada, o me encuentras en Twitter acá. Si quieres saber más sobre mí puedes hacerlo leyendo aquí.