Planeación de pruebas de carga mediante Apache JMeter

Completado

En esta sección, explorará las pruebas de carga y aprenderá a agregar pruebas de carga a la canalización. Las pruebas de carga usan Apache JMeter para simular que varios usuarios acceden a la aplicación web simultáneamente. Las pruebas capturan el contenido web de la aplicación que se ejecuta en Azure App Service en el entorno de Ensayo.

Tim empieza por introducir la interfaz de usuario de Apache JMeter en un equipo portátil. Ejecuta un plan de pruebas básico. A continuación, Tim y Mara exportan el plan de pruebas a un archivo que se puede ejecutar desde la línea de comandos. Finalmente, agregan tareas a Azure Pipelines para ejecutar las pruebas de carga durante la fase de Ensayo.

Nota:

Por motivos de brevedad, no es necesario instalar Apache JMeter en el equipo local. Puede seguir leyendo.

Ejecución de pruebas de carga desde Apache JMeter

Apache JMeter es una herramienta de pruebas de carga de código abierto que analiza y mide el rendimiento. El informe que genera es un archivo XML.

Azure Pipelines puede leer el informe de Apache JMeter y generar un grafo. No necesita ningún hardware especial para ejecutar estas pruebas, por lo que puede usar un agente hospedado por Microsoft para ejecutarlas. En el escenario de Space Game, es probable que ejecute estas pruebas en Almacenamiento provisional.

Creación del plan de pruebas

Este es el aspecto de Apache JMeter en un equipo portátil que ejecuta Linux:

Screenshot of the Apache JMeter user interface.

Crearía un nuevo archivo de plan de prueba; por ejemplo, LoadTest.jmx. A continuación, agregaría un grupo de subprocesos al archivo. Cada usuario simulado se ejecuta en su propio subproceso. Un grupo de subprocesos controla el número de usuarios y el número de solicitudes de cada usuario.

En el ejemplo siguiente se muestran 10 usuarios simulados (subprocesos). Cada usuario realiza 10 solicitudes, por lo que el sistema obtiene un total de 100 solicitudes.

Screenshot of specifying the thread group in Apache JMeter.

Una muestra es una solicitud individual realizada por JMeter. JMeter puede consultar servidores a través de HTTP, FTP, TCP y otros protocolos. Las muestras generan los resultados que se agregan al informe.

A continuación, agregaría valores predeterminados de solicitud HTTP y una muestra de solicitud HTTP al grupo de subprocesos. Proporcionaría el nombre de host del sitio web de Space Game que ejecuta en el entorno de ensayo en Azure App Service.

Screenshot that shows specifying the HTTP request in Apache JMeter.

En el escenario anterior se crea un plan de prueba básico.

Ejecución del plan de pruebas

JMeter te permite ejecutar muchos tipos de pruebas. El plan de pruebas se puede ejecutar desde la interfaz gráfica de usuario de JMeter. Sin embargo, para las pruebas de carga, la documentación de JMeter recomienda ejecutar el plan de pruebas desde la línea de comandos.

Ejecutaría el plan de prueba mediante este comando:

apache-jmeter-5.4.1/bin/./jmeter -n -t LoadTest.jmx -o Results.xml

El argumento -n especifica que JMeter se ejecute en modo no GUI. El argumento -t especifica el archivo del plan de pruebas, LoadTest.jmx. El argumento -o especifica el archivo de informe, Results.xml.

JMeter se ejecuta y genera el archivo de informe Results.xml. En este ejemplo del archivo, se muestran los primeros resultados:

<?xml version="1.0" encoding="UTF-8"?>
<testResults version="1.2">
<httpSample t="180" it="0" lt="95" ct="35" ts="1569306009772" s="true" lb="HTTP Request" rc="200" rm="OK" tn="Thread Group 1-1" dt="text" by="40871" sby="144" ng="1" na="1">
  <java.net.URL>http://tailspin-space-game-web-staging-1234.azurewebsites.net/</java.net.URL>
</httpSample>
<httpSample t="174" it="0" lt="96" ct="38" ts="1569306009955" s="true" lb="HTTP Request" rc="200" rm="OK" tn="Thread Group 1-1" dt="text" by="40869" sby="144" ng="1" na="1">
  <java.net.URL>http://tailspin-space-game-web-staging-1234.azurewebsites.net/</java.net.URL>
</httpSample>
<httpSample t="160" it="0" lt="121" ct="35" ts="1569306010131" s="true" lb="HTTP Request" rc="200" rm="OK" tn="Thread Group 1-1" dt="text" by="40879" sby="144" ng="2" na="2">
  <java.net.URL>http://tailspin-space-game-web-staging-1234.azurewebsites.net/</java.net.URL>
</httpSample>

Cada muestra produce un nodo en el informe. El atributo t especifica el tiempo de respuesta en milisegundos (ms). Aquí ve tres solicitudes que tardaron 180 ms, 174 ms y 160 ms.

Los tiempos de solicitud ideales deberían ser, de media, inferiores a un segundo. No más del 10 por ciento de las solicitudes deben tardar más de un segundo. Puedes configurar JMeter para informar de estadísticas como los tiempos de respuesta mínimo, máximo y medio, o la desviación estándar. Puede escribir un script para ayudar a proporcionar esta información.

Para visualizar los resultados de la prueba, debe proporcionarlos en un formato que Azure Pipelines comprenda. Azure Pipelines puede analizar un archivo XML que contiene resultados de pruebas, pero el archivo debe tener un formato admitido. Entre los formatos admitidos se incluyen CTest, JUnit (incluido PHPUnit), NUnit 2, NUnit 3, Visual Studio Test (TRX) y xUnit 2. Puede escribir un archivo XSLT que convierta los resultados de JMeter en JUnit.

Transformación del informe en JUnit

XSLT significa Transformaciones XSL o lenguaje de transformación basado en hojas de estilo. Un archivo XSLT se parece a un archivo XML, pero le permite transformar un documento XML a otro formato XML.

Recuerde nuestros requisitos para las pruebas de carga:

  • El tiempo de solicitud medio debe ser inferior a un segundo.
  • No más del 10 por ciento de las solicitudes deben tardar más de un segundo.

Este es el aspecto de un archivo XSLT que cumple estos requisitos:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:math="http://exslt.org/math">
  <xsl:output method="xml" indent="yes" encoding="UTF-8"/>
  <xsl:template match="/testResults">
    <xsl:variable name="times" select="./httpSample/@t" />
    <xsl:variable name="failures" select="./httpSample/assertionResult/failureMessage" />
    <xsl:variable name="threshold" select="1000" />
    <testsuite>
      <xsl:attribute name="tests"><xsl:value-of select="count($times)" /></xsl:attribute>
      <xsl:attribute name="failures"><xsl:value-of select="count($failures)" /></xsl:attribute> 
      <testcase>
          <xsl:variable name="avg-time" select="sum($times) div count($times)" />
          <xsl:attribute name="name">Average Response Time</xsl:attribute>
          <xsl:attribute name="time"><xsl:value-of select="format-number($avg-time div 1000,'#.##')"/></xsl:attribute>
          <xsl:if test="$avg-time > $threshold">
            <failure>Average response time of <xsl:value-of select="format-number($avg-time,'#.##')"/> exceeds <xsl:value-of select="$threshold"/> ms threshold.</failure>
          </xsl:if> 
      </testcase>
      <testcase>
          <xsl:variable name="exceeds-threshold" select="count($times[. > $threshold])" />
          <xsl:attribute name="name">Max Response Time</xsl:attribute>
          <xsl:attribute name="time"><xsl:value-of select="math:max($times) div 1000"/></xsl:attribute>
          <xsl:if test="$exceeds-threshold > count($times) * 0.1">
            <failure><xsl:value-of select="format-number($exceeds-threshold div count($times) * 100,'#.##')"/>% of requests exceed <xsl:value-of select="$threshold"/> ms threshold.</failure>
          </xsl:if>
      </testcase>
    </testsuite>
  </xsl:template>
</xsl:stylesheet>

No profundizaremos en el funcionamiento de XSL. Pero, para resumirlo, este archivo primero recopila los datos siguientes de la salida de JMeter:

  • Cada tiempo de solicitud HTTP.

    Recopila estos datos seleccionando el atributo t de cada elemento httpSample. (./httpSample/@t)

  • Cada mensaje de error.

    Recopila estos datos seleccionando los nodos failureMessage del documento. (./httpSample/assertionResult/failureMessage)

El archivo XSLT también establece el valor de umbral en 1000 ms. Este tiempo de respuesta es el máximo que definimos anteriormente.

Dadas estas variables, el archivo XSLT proporciona el número total de pruebas y el número total de errores. A continuación, proporciona estos dos casos de prueba:

  • El tiempo de respuesta medio y un error si el promedio supera el umbral de 1000 ms.
  • El tiempo de respuesta máximo y un error si más del 10 por ciento de las solicitudes superan el umbral de 1000 ms.

Los resultados de XSLT coinciden con el formato JUnit, que Azure Pipelines entiende. Podría asignar un nombre al archivo XSLT JMeter2JUnit.xsl.

A continuación, necesitará un procesador XSLT. En este ejemplo, usaremos xsltproc, que es una herramienta de línea de comandos para aplicar hojas de estilos XSLT a documentos XML.

Puede instalar xsltproc de la siguiente manera:

sudo apt-get install xsltproc

A continuación, ejecutaría xsltproc para transformar el informe JMeter en JUnit:

xsltproc JMeter2JUnit.xsl Results.xml > JUnit.xml

Este es el archivo JUnit resultante, JUnit.xml:

<?xml version="1.0" encoding="UTF-8"?>
<testsuite xmlns:math="http://exslt.org/math" tests="100" failures="0">
  <testcase name="Average Response Time" time="0.17"/>
  <testcase name="Max Response Time" time="0.373"/>
</testsuite>

En este ejemplo, el tiempo de respuesta medio es de 170 ms. El tiempo de respuesta máximo es de 373 ms. Ninguno de los casos de prueba genera un error porque ambos tiempos están por debajo del umbral de 1000 ms.

En breve, ejecutará estas pruebas en la canalización. Puede pensar en Results.xml, el archivo que escribe JMeter, como un archivo intermedio que no se publica en los resultados de las pruebas de la canalización. JUnit.xml es el archivo de informe final. Este archivo se publica en la canalización para que el equipo pueda ver los resultados.