Planejar testes de carga usando o Apache JMeter

Concluído

Nesta seção, você explorará o teste de carga e aprenderá como adicionar testes de carga ao pipeline. Os testes de carga usam o Apache JMeter para simular vários usuários que acessam o aplicativo Web simultaneamente. Os testes buscam o conteúdo da Web do aplicativo executado no Serviço de Aplicativo do Azure no ambiente de Preparo .

Tim começa exibindo a interface de usuário do Apache JMeter em um laptop. Ele executa um plano de teste básico. Em seguida, Tim e Mara exportam o plano de teste para um arquivo que pode ser executado a partir da linha de comando. Finalmente, eles adicionam tarefas aos Pipelines do Azure para executar os testes de carga durante o preparo.

Nota

Para maior brevidade, não é necessário instalar o Apache JMeter no computador local. Você pode apenas ler junto.

Executar testes de carga do Apache JMeter

Apache JMeter é uma ferramenta de teste de carga de código aberto que analisa e mede o desempenho. O relatório que ele gera é um arquivo XML.

Os Pipelines do Azure podem ler o relatório Apache JMeter e gerar um gráfico. Você não precisa de nenhum hardware especial para executar esses testes, portanto, pode usar um agente hospedado pela Microsoft para executá-los. No cenário Jogo Espacial, você provavelmente executaria esses testes em Preparo.

Criar o plano de teste

Veja como o Apache JMeter se parece em um laptop rodando Linux:

Screenshot of the Apache JMeter user interface.

Você criaria um novo arquivo de plano de teste; por exemplo, LoadTest.jmx. Em seguida, você adicionaria um Grupo de Threads ao arquivo. Cada usuário simulado é executado em seu próprio thread. Um grupo de threads controla o número de usuários e o número de solicitações de cada usuário.

O exemplo a seguir mostra 10 usuários simulados (threads). Cada utilizador faz 10 pedidos, pelo que o sistema recebe um total de 100 pedidos.

Screenshot of specifying the thread group in Apache JMeter.

Um amostrador é uma única solicitação feita pela JMeter. O JMeter pode consultar servidores através de HTTP, FTP, TCP e vários outros protocolos. Os amostradores geram os resultados que são adicionados ao relatório.

Em seguida, você adicionaria Padrões de Solicitação Http e um amostrador de Solicitação Http ao grupo de threads. Você forneceria o nome do host do site do Jogo Espacial que é executado no ambiente de preparo no Serviço de Aplicativo do Azure.

Screenshot that shows specifying the HTTP request in Apache JMeter.

O cenário anterior cria um plano de teste básico.

Executar o plano de teste

O JMeter permite que você execute muitos tipos de testes. É possível executar seu plano de teste a partir da interface gráfica do usuário JMeter. Para testes de carga, no entanto, a documentação do JMeter recomenda que você execute o plano de teste a partir da linha de comando.

Você executaria o plano de teste usando este comando:

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

O -n argumento especifica para executar JMeter no modo não-GUI. O -t argumento especifica o arquivo de plano de teste, LoadTest.jmx. O -o argumento especifica o arquivo de relatório, Results.xml.

O JMeter executa e produz o arquivo de relatório, Results.xml. Este exemplo do arquivo mostra os primeiros 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 exemplo produz um nó no relatório. O t atributo especifica o tempo de resposta em milissegundos (ms). Aqui, você vê três solicitações que levaram 180 ms, 174 ms, e 160 ms.

Os tempos ideais de solicitação devem ser, em média, inferiores a um segundo. Não mais de 10% dos pedidos devem demorar mais de um segundo. Você pode configurar o JMeter para relatar estatísticas como os tempos de resposta mínimo, máximo e médio ou o desvio padrão. Você pode escrever um script para ajudar a fornecer essas informações.

Para visualizar os resultados do teste, você precisa fornecê-los em um formato que o Azure Pipelines entenda. O Azure Pipelines pode analisar um arquivo XML que contém resultados de teste, mas o arquivo precisa estar em um formato com suporte. Os formatos suportados incluem CTest, JUnit (incluindo PHPUnit), NUnit 2, NUnit 3, Visual Studio Test (TRX) e xUnit 2. Você pode escrever um arquivo XSLT que converte os resultados do JMeter em JUnit.

Transformar o relatório em JUnit

XSLT significa XSL Transformations, ou eXtensible Stylesheet Language Transformations. Um arquivo XSLT se assemelha a um arquivo XML, mas permite transformar um documento XML em outro formato XML.

Relembre nossos requisitos para testes de carga:

  • O tempo médio de solicitação deve ser inferior a um segundo.
  • Não mais de 10% dos pedidos devem demorar mais de um segundo.

Veja a aparência de um arquivo XSLT que atende a esses 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>

Não vamos nos aprofundar em como o XSL funciona aqui. Mas, para resumir, esse arquivo primeiro coleta os seguintes dados da saída JMeter:

  • Cada tempo de solicitação HTTP.

    Ele coleta esses dados selecionando o t atributo de cada httpSample elemento. (./httpSample/@t)

  • Cada mensagem de falha.

    Ele coleta esses dados selecionando todos os failureMessage nós do documento. (./httpSample/assertionResult/failureMessage)

O arquivo XSLT também define o valor limite para 1.000 ms. Este tempo de resposta é o máximo que definimos anteriormente.

Dadas essas variáveis, o arquivo XSLT fornece o número total de testes e o número total de falhas. Em seguida, fornece estes dois casos de teste:

  • O tempo médio de resposta e uma falha se a média exceder o limite de 1.000 ms.
  • O tempo máximo de resposta e uma falha se mais de 10% das solicitações excederem o limite de 1.000 ms.

Os resultados do XSLT correspondem ao formato JUnit, que o Azure Pipelines entende. Você pode nomear seu arquivo XSLT JMeter2JUnit.xsl.

Em seguida, você precisaria de um processador XSLT. Neste exemplo, usaremos xsltproc, que é uma ferramenta de linha de comando para aplicar folhas de estilo XSLT a documentos XML.

Você pode instalar o xsltproc da seguinte maneira:

sudo apt-get install xsltproc

Em seguida, você executaria xsltproc para transformar o relatório JMeter em JUnit:

xsltproc JMeter2JUnit.xsl Results.xml > JUnit.xml

Aqui está o arquivo 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>

Neste exemplo, o tempo médio de resposta é de 170 ms. O tempo máximo de resposta é de 373 ms. Nenhum caso de teste gera uma falha, porque ambas as vezes ficam abaixo do limiar de 1.000 ms.

Em breve, você executará esses testes no pipeline. Você pode pensar em Results.xml, o arquivo que o JMeter escreve, como um arquivo intermediário que não é publicado nos resultados de teste do pipeline. JUnit.xml é o arquivo de relatório final. Esse arquivo é publicado no pipeline para que a equipe possa visualizar os resultados.