Me he visto recientemente involucrado en el proceso de selección de una herramienta para el testeo de aplicaciones web. Sobre todo para el análisis del rendimiento de la mismas. Evidentemente yo estaba presente en este proceso para comentar las excelencias de Visual Studio Team System for Testers en este campo, que son muchas.
Yo defendía claramente la superioridad y capacidad técnica de VSTS for Testers a la hora de dotar al equipo de desarrollo con un entorno integrado, completo y ágil a la hora de hacer pruebas. La parte ‘contraria’, representante de una de esas empresas que, tras competir con dudoso existo (a tenor de los resultados económicos) con Microsoft en el terreno del software privativo, se ha convertido al software libre con la vehemencia del nuevo creyente, no contaba con una solución, ni de lejos, comparable a las posibilidades de VSTS for Testers. La solución que proponian: una herramienta de stress más un profiler, solución a todas luces insuficiente, pero la única que podían ofrecer.
Supongo que debe ser alguna táctica comercial bien estudiada, el que ante la certeza de que estas en inferioridad, la mejor manear de capear situación es tratar de hacer ver que no son necesarias las capacidades que la solución de tu competidor te ofrece. Aunque en tu fuero interno sepas que no estás diciendo la verdad. Otra cosa curiosa es como en cierto momento la situación giro a que se usase lo que se usase, no fuese un producto de Microsoft. Como si usar productos que no sean de Microsoft (no ya que sean libres) fuese directamente bueno para el proyecto o te dotase incluso de superioridad moral. Y la verdad, eso es algo que me revienta. Si somos técnicos, somos técnicos y debemos admirar las grandes soluciones vengan de donde venga. Aunque vengan de Microsoft. Sobre todo cuando nuestro trabajo es el de expertos independientes.
Pero bueno, volvamos al grano, y a lo me que ha motivado ha escribir este post: por qué una herramienta de stress y un profiler, aunque herramientas imprescindibles, no son herramientas suficientes y menos aun optimas para hacer pruebas de carga y analizar los resultados, y por qué VSTS for Testers si es una solución completa y potente.
Cuando nos planteamos hacer pruebas de carga, evidentemente, necesitamos una aplicación que sea capaz de generar de manera simple, repetible, distribuida, suficiente, y controlada peticiones a la aplicación que queremos someter a estres. Además debe poder añadir esta carga incrementalmente o buscando ciertos objetivos de utilización recursos (tests guiados por objetivos, en plan, añade peticiones hasta que el procesador del servidor de bases de datos llegue al 80% y mantenla, imprescindibles para poder hacer capacity planning). Evidentemente esta aplicación debe ser capaz de hacer muchas otras cosas como utilizar diferentes juegos de datos, darnos información sobre los recursos que consume para generar el estrés (debemos saber si el cuello de botella está en el propio generador de carga o en la aplicación), los test que ejecuta en un tiempo dado y cuantos de ellos cumplen las postcondiciones que se hayan podido establecer y cuantos son erroneos por no cumplirlas. Además, lógicamente, debe ser capaz de generar peticiones según los protocolos usados en la arquítectura, pues por ejemplo, no todas la herramientas se comportan bien cuando hay Ajax de por medio. Evidentemente VSTS for Testers nos permite todo esto. Podéis en la imagen siguiente ver como es la definición de un test.
Pero esto no es suficiente para que las pruebas de carga sean significativas. Sería sufiente si simplemente quisiesemos poner fuerza bruta en la aplicación bajo testeo hasta que esta ‘cascase’ por algún lado. Pero ese es un objetivo poco ambicioso que a duras penas justifica el esfuerzo de montar un entorno de pruebas, crear pruebas y contar con un equipo de testers. Si hacemos pruebas de carga las tenemos que hacer con un proposito claro: mejorar el rendimiento de la aplicación y en consecuencia, su escalabilidad, no simplemente nos debe valer el saber los límites de nuestra aplicación. Y para esto debemos ser capaces de detectar cuellos de botella. Esto es lo realmente importante de las pruebas de carga: detectar cuellos de botella. Saber que recursos hacen que nuestra aplicación no se ejecute más rápido y sobre todo, saber donde debemos centrar nuestro esfuerzo económico, bien en forma de más hardware o bien en forma de esfuerzos de optimización.
Hoy en día las aplicaciones son cada vez más distribuidas y más orientadas a servicios. La consecuencia clara es que el rendimiento de nuestra aplicación depende de un gran número de factores, dispersos por un gran número de máquinas y por un gran número de aplicaciones, que proporcionan diferentes servicios. En esta situación pretender que un profiler junto con una aplicación que genere carga es una solución suficiente es cuando menos miope. Solo si tu entorno de pruebas es capaz de monitorizar como se comportan todos los sistemas implicados en la prueba podrás detectar los cuellos de botella que se producen en el sistema y una vez claramente identificados ajustar el hardware, la aplicación o el código (en este caso si, siempre usando la imprescindible ayuda de un profiler). Pero prenterde utilizar en un sistema distribuido un profiler como única herrmienta es absurdo ¿vas a ir ‘enchufando’ profilers a todos los componentes de tu aplicación? ¿Y que pasa si el cuello de botella está en la saturación de red, algo que nunca verías con un profiler? ¿Y si tua aplicación usa colas y este es el cuello de botella, algo que nunca verás tampoco con un profiler?. En la siguiente imagen podéis ver como VSTS recolecta la información que deseemos sobre el progreso de la prueba.
Conscientes de esto, Microsoft nos proporciona una solución completa con VSTS for Testers, que permite lanzar pruebas distribuidas desde un único PC y monitorizar desde este mismo, en tiempo real, como se comportan todos los elementos, a nivel de hardware o de software implicados en la prueba. De esta manera, el proceso de pruebas es completo, repetible y significativo.
La forma de actuar es la siguiente: defines la prueba, defines los parámetros relevantes desde el punto de vista del rendimiento que quieres monitorizar, lanzas la prueba, y durante la realización de la misma VSTS recolecta todos los parámetros relevantes, avisandono además cuando alguno se sale de magnitudes normales. Luego utilizando el conocimiento que tenemos del sistema y de su arquitectura analizaremos los datos recolectados sobre el conjunto del sistema bajo prueba para buscar aquellos cuellos de botella que merezcan nuestra atención. Si estos están en nuestros componentes, entonces usaremos un profiler para hilar fino y ver que problemas puede haber en nuestro código que esten dañando el desempeño del sistema en su conjunto.
Utilizar únicamente una herramienta de generación de carga y un profiler es como disparar al aire con la intención de cazar algo. Previo al uso de un profiler, es necesario hacer un análisis de más alto nivel, por simple economía de recursos.