Apache JMeter: realize testes de carga e performance em aplicações

Apache JMeter: realize testes de carga e performance em aplicações
Rodrigo da Silva Ferreira Caneppele
Rodrigo da Silva Ferreira Caneppele

Compartilhe

Durante o processo de desenvolvimento de software, é comum que os times de desenvolvimento e qualidade (QA) concentrem seus esforços principalmente em testes funcionais, que visam garantir que as diversas funcionalidades da aplicação estejam operando corretamente.

No entanto, além dos testes funcionais, há uma categoria igualmente importante: os testes não funcionais, que têm como objetivo avaliar aspectos como performance, escalabilidade, segurança e usabilidade da aplicação.

É bastante comum que as pessoas desenvolvedoras tenham uma percepção positiva da performance da aplicação, uma vez que todas as funcionalidades são executadas sem problemas aparentes de lentidão ou gargalos.

No entanto, é importante lembrar que esses testes são geralmente realizados em ambientes de desenvolvimento, ou seja, nos próprios computadores das pessoas desenvolvedoras.

Os ambientes de produção, onde as aplicações serão implantadas, geralmente possuem configurações de hardware distintas, além de volumes de dados muito maiores do que os encontrados nos ambientes de desenvolvimento.

Por exemplo, enquanto o banco de dados em ambiente de desenvolvimento pode conter apenas algumas dezenas ou centenas de registros em suas tabelas, no ambiente de produção esse número pode ser exponencialmente maior, chegando a bilhões ou mesmo trilhões de registros.

A negligência na performance de uma aplicação pode acarretar diversos impactos para uma empresa.

Por exemplo, pode causar tempos de carregamento longos, levando os usuários a abandonar a plataforma em busca de alternativas mais rápidas.

Isso prejudica a experiência do cliente, podendo também afetar a reputação da empresa e resultar em perdas financeiras.

Portanto, os testes de performance realizados em ambientes de desenvolvimento podem não refletir de forma precisa o comportamento da aplicação em produção.

É fundamental simular condições realistas de uso, como um alto número de usuários simultâneos e uma alta carga de uso.

Isso pode ser feito via testes de carga e performance utilizando algumas ferramentas, como o Apache JMeter, que são capazes de simular cenários complexos de uso e fornecer feedbacks sobre o desempenho da aplicação em ambientes simulados de produção.

O que é Apache JMeter

O Apache JMeter é uma ferramenta de testes de performance utilizada por times de desenvolvimento e QA.

Desenvolvida e mantida pela Apache Software Foundation, o JMeter é uma aplicação open source escrita em Java, o que a torna bastante portátil e compatível com muitas tecnologias.

O JMeter permite a execução de testes em diversas aplicações e protocolos, incluindo aplicações Web, bancos de dados, servidores de aplicações, entre outros.

É possível simular diferentes cenários de carga, permitindo avaliar como uma aplicação responde sob diferentes níveis de tráfego e utilização.

Banner da promoção da black friday, com os dizeres: A Black Friday Alura está chegando. Faça parte da Lista VIP, receba o maior desconto do ano em primeira mão e garanta bônus exclusivos. Quero ser VIP

Como fazer download do Apache JMeter

O JMeter pode ser baixado neste link e como se trata de uma aplicação Java ele não é instalado no computador, devendo apenas ser executado.

O requisito para sua execução é ter o Java na versão 8 ou superior instalado no computador.

Após realizar o download do arquivo .zip, basta descompactá-lo em algum diretório do seu computador.

Execução

Para executar o JMeter, basta abrir o terminal ou prompt de comandos, navegar até o diretório onde ele foi descompactado e executar o seguinte comando:

java -jar bin/ApacheJMeter.jar

Será aberta a tela principal do JMeter:

Tela inicial da ferramenta Apache JMeter. Na parte superior tem a barra de menu principal e abaixo dela existe uma lista de ícones com as principais ações que podem ser executadas. A parte principal, localizada abaixo a lista de ícones, é dividida em dois blocos, sendo que o bloco à esquerda contém a lista de planos de teste e o bloco à direita exibe os detalhes do plano de teste selecionado.

O JMeter vem configurado com o idioma Inglês, mas é possível alterar para o Português acessando a opção Choose Language, que está localizada no menu superior Options.

Plano de teste

Ao iniciar o JMeter, perceba que existe um elemento chamado Test Plan (plano de teste) já criado por padrão.

O Test Plan é o ponto de partida para criar e executar os testes no JMeter. Ele funciona como uma espécie de esqueleto para toda a estrutura do teste, definindo os cenários a serem simulados, os protocolos a serem utilizados e as métricas a serem avaliadas.

Nele, você define todos os elementos necessários para configurar e executar seus testes, incluindo a configuração de servidores, threads (usuários virtuais), grupos de amostras, controladores, listeners (ouvintes), entre outros elementos. Cada um desses elementos desempenha um papel específico no teste.

Projeto de exemplo

Para facilitar o entendimento do funcionamento do JMeter, em relação ao test plan e seus elementos, vamos a um exemplo prático.

Suponha que você desenvolveu uma API Rest de um e-commerce e nela exista um endpoint que você deseja testar com o JMeter:

  1. GET /produtos -> Endpoint público para listar os produtos cadastrados

Vamos configurar o teste para um cenário que consiste em simular 500 usuários disparando requisições, de maneira simultânea, para o endpoint de listagem de produtos.

Primeiramente, vamos renomear o test plan, selecionando o test plan criado por padrão no JMeter no lado esquerdo da tela e digitando Listagem de produtos no campo Name, no lado direito da tela:

Tela de detalhes do Test Plan no JMeter com o texto “Listagem de produtos” no campo “Name”.

Após isso, vamos salvar o test plan em nosso computador pela opção Save, localizada no menu superior File, ou utilizando o atalho CTRL + S:

Janela aberta no JMeter ao escolher a opção de salvar o test plan no computador.

Escolha um diretório de sua preferência em seu computador e salve o test plan. Repare que o JMeter criará um arquivo com a extensão .jmx no diretório escolhido.

Thread Group

O próximo passo será configurar o teste para que realize uma simulação de 500 usuários simultâneos disparando requisições para a API.

Essa configuração deve ser feita via adição do elemento Thread Group ao test plan.

O Thread Group representa um grupo de usuários virtuais que vai interagir com a aplicação durante o teste.

Cada Thread Group define o número de usuários virtuais (ou threads) que serão simulados, bem como a forma como esses usuários vão se comportar ao longo do teste, incluindo aspectos como o tempo de inicialização dos usuários, o tempo de espera entre as requisições e a duração total do teste.

Além disso, também é possível configurar o comportamento dos usuários em relação aos erros, definindo se uma thread deve continuar executando mesmo após encontrar um erro ou se deve interromper imediatamente.

Para adicionar um Thread Group ao Test Plan, basta clicar com o botão direito no Test Plan e escolher escolher a opção: Add -> Threads (Users) -> Thread Group:

Opção para adicionar um Thread Group ao Test Plan exibida ao clicar com o botão direito do mouse no Test Plan “Listagem de produtos” e escolher a opção “Add Threads (Users)”.

Será exibida a tela de configuração do Thread Group, conforme demonstrada na imagem abaixo:

Tela de configurações do Thread Group. O campo “Name” está preenchido com o texto “500 usuários”, o campo “Comments” foi deixado em branco, o campo “Action to be taken after a Sampler error” está com a opção “Continue” selecionada, o campo “Number of Threads (users)” está com o valor 500, o campo “Ramp-up period (seconds)” está com o valor 1, o campo “Loop Count” está com a opção “Infinite” desmarcada e com o valor 1 digitado, a opção “Same user on each iteration” está marcada, os campos “Delay Thread creation until needed” e “Specify Thread lifetime” estão desmarcadas e os campos “Duration (seconds)” e “Startup delay (seconds)” estão em branco.

Nesta tela, existem diversos campos para realizar a configuração do Thread Group. A seguir, uma explicação do que significa cada um desses campos:

  • Name: Este campo permite atribuir um nome ao Thread Group para identificação e organização dentro do Test Plan;
  • Comments: Este campo permite adicionar comentários ou notas relevantes ao Thread Group;
  • Action to be taken after a Sampler error: Este campo define o comportamento a ser adotado pelo Thread Group caso um erro ocorra durante a execução dos testes;
  • Number of Threads (users): Este campo define o número total de usuários virtuais (threads) que serão simulados pelo Thread Group durante o teste;
  • Ramp-up period (seconds): Este campo especifica o tempo, em segundos, que o Thread Group levará para adicionar gradualmente os usuários virtuais até atingir o número definido em "Number of Threads (users)";
  • Loop Count: Este campo define o número de vezes que o Thread Group executará o conjunto de requisições. Se a opção Infinite for marcada, o teste será executado infinitamente, devendo ser finalizado manualmente;
  • Same user on each iteration: Esta opção determina se o mesmo usuário virtual será usado em cada iteração do loop. Quando marcada, o mesmo usuário será mantido em todas as iterações;
  • Delay Thread creation until needed: Esta opção indica se a criação das threads será adiada até que sejam necessárias. Quando marcada, as threads serão criadas apenas quando a execução começar;
  • Specify Thread lifetime: Esta opção permite especificar a duração de vida das threads, ou seja, quanto tempo cada thread será mantida ativa durante o teste;
  • Duration (seconds): Este campo permite definir a duração total do teste, em segundos;
  • Startup delay (seconds): Este campo especifica um atraso inicial, em segundos, antes do início da execução do teste.

Sampler

Uma vez configurado o Thread Group, devemos indicar ao JMeter o que esse Thread Group em específico deve fazer, ou seja, devemos configurar as ações que serão realizadas durante a execução do teste. Isso deve ser feito com a adição de um Sampler ao Thread Group.

O Sampler é responsável por simular uma ação específica que um usuário real poderia realizar ao interagir com a aplicação.

Isso pode incluir o envio de uma requisição HTTP, a execução de uma consulta SQL em um banco de dados, entre outros.

Cada Sampler representa um tipo de ação que pode ser executada pelos usuários virtuais durante o teste.

Para adicionar um Sampler ao Thread Group, basta clicar com o botão direito no Thread Group e escolher escolher a opção: Add -> Sampler:

Opção para adicionar um Sampler ao Thread Group exibida ao clicar com o botão direito do mouse no Thread Group “500 usuários” e escolher a opção “Add -> Sampler”.

Repare que nessa opção existem diversos tipos distintos de Samplers que podem ser adicionados ao Thread Group, sendo que cada um deles serve para realizar um tipo específico de ação.

No nosso caso, vamos escolher o Sampler do tipo HTTP Request, pois nosso teste consiste em disparar requisições HTTP para a API.

Ao selecionar essa opção, será exibida a tela de configuração do Sampler, conforme demonstrado na imagem a seguir:

Tela de configurações do Sampler HTTP Request. O campo “Name” está preenchido com o texto “GET /produtos”, o campo “Comments” foi deixado em branco, o campo “Protocol [http]” está preenchido com o texto “http”, o campo “Server Name or IP” está preenchido com o texto “localhost”, o campo “Port Number” está preenchido com o texto “8080”, na seção “HTTP Request” a opção “GET” está selecionada, o campo “Path” está preenchido com o texto “/produtos”, o campo “Content encoding” foi deixado em branco, as opções “Redirect Automatically”, “Use multipart/form-data” e “Browser-compatible headers” estão desmarcadas, e as opções “Follow Redirects” e “Use KeepAlive” estão marcadas.

Nesta tela, existem diversos campos para realizar a configuração do Sampler HTTP Request. A seguir, uma explicação do que significa cada um desses campos:

  • Name: Este campo permite atribuir um nome ao Sampler HTTP Request para identificação e organização dentro do Thread Group;
  • Comments: Este campo permite adicionar comentários ou notas relevantes ao Sampler HTTP Request;
  • Protocol [http]: Este campo define o protocolo a ser utilizado para a requisição;
  • Server Name or IP: Este campo especifica o nome do servidor ou o endereço IP para o qual a requisição HTTP será enviada;
  • Port Number: Este campo define o número da porta a ser utilizada para a conexão com o servidor;
  • HTTP Request: Nesta seção, são configuradas as opções específicas da requisição HTTP;
  • Method: Esta opção define o método HTTP a ser utilizado na requisição, como GET, POST, entre outros;
  • Path: Este campo especifica o caminho (path) da URL para a qual a requisição será enviada;
  • Content encoding: Este campo permite especificar a codificação do conteúdo da requisição, se necessário;
  • Redirect Automatically, Use multipart/form-data e Browser-compatible headers: Estas opções definem o comportamento da requisição em relação a redirecionamentos, uso de formulários multipartes (usados com upload de arquivos) e cabeçalhos compatíveis com o navegador;
  • Follow Redirects e Use KeepAlive: Estas opções configuram se o JMeter deve seguir automaticamente os redirecionamentos e se deve manter a conexão ativa (KeepAlive) após a requisição.

Você deve configurar os valores nesta tela de acordo com a aplicação que você deseja testar.

É possível executar os testes do JMeter localmente, em ambiente de desenvolvimento, bastando executar a aplicação em seu computador e digitar localhost no campo Server Name or IP.

Mas lembre-se de que o ideal é sempre testar no ambiente de produção, quando isso for possível, ou então em um ambiente de testes/homologação que seja o mais próximo possível do ambiente de produção.

A partir deste ponto já podemos executar os testes no JMeter. Porém, para conseguir visualizar o resultado dos testes é necessário adicionar mais um elemento ao nosso Test Plan.

LIstener

Os Listeners são componentes responsáveis por coletar e exibir os resultados dos testes de performance realizados.

Eles auxiliam na análise dos dados gerados durante os testes, permitindo avaliar o desempenho da aplicação e identificar possíveis gargalos.

Os Listeners funcionam como "ouvintes" que capturam e exibem os dados gerados durante a execução dos testes.

Eles podem exibir uma variedade de informações, como tempos de resposta, taxas de erro, entre outras.

Cada tipo de Listener oferece uma visualização específica dos dados, permitindo analisar diferentes aspectos do desempenho da aplicação.

Para adicionar um Listener ao Thread Group, basta clicar com o botão direito no Thread Group e escolher escolher a opção: Add -> Listener:

Opção para adicionar um Listener ao Thread Group exibida ao clicar com o botão direito do mouse no Thread Group “500 usuários” e escolher a opção “Add -> Listener”.

O JMeter disponibiliza alguns Listeners prontos para uso, cada um projetado para atender a diferentes necessidades de análise de resultados.

Os três principais, que são mais comuns de serem utilizados, são:

  • View Results Tree: Exibe os resultados detalhados de cada amostra de teste;
  • Summary Report: Fornece uma visão geral resumida dos resultados;
  • Aggregate Report: Apresenta estatísticas agregadas sobre o desempenho do teste.

Ao escolher, por exemplo, o Listener do tipo Aggregate Report, será exibida a seguinte tela:

Tela de configurações do Listener Aggregate Report. O campo “Name” está preenchido com o texto “Aggregate Report” e os campos “Comments” e “Filename” foram deixados em branco.

Esse relatório exibe uma tabela com dados de estatísticas relacionados à performance da aplicação, em relação aos testes que foram executados pelo JMeter.

São dados muito valiosos e que devem ser analisados pelo time de desenvolvimento para encontrar possíveis gargalos na aplicação.

Os dados exibidos nessa tabela são:

  • Label: Esta coluna exibe o rótulo (label) atribuído a cada amostra de teste. O rótulo geralmente corresponde à ação ou requisição realizada durante o teste, como "GET /produtos" ou "POST /login";
  • Samples: Esta coluna exibe o número total de amostras (ou requisições) executadas durante o teste para cada label específico;
  • Average: Esta coluna exibe o tempo médio de resposta para cada amostra, ou seja, o tempo médio que a aplicação leva para responder a uma requisição;
  • Median: Esta coluna exibe a mediana dos tempos de resposta para cada amostra. A mediana representa o valor central de um conjunto de dados ordenado;
  • 90% Line: Esta coluna exibe o tempo de resposta que foi igualado ou superado em 90% das amostras. Isso é útil para avaliar o desempenho da aplicação sob condições de uso normais;
  • 95% Line e 99% Line: Estas colunas exibem mostram os tempos de resposta que foram igualados ou superados em 95% e 99% das amostras, respectivamente. Essas métricas ajudam a identificar possíveis gargalos ou problemas de desempenho em cenários de uso mais extremos;
  • Min e Maximum: Estas colunas exibem o tempo mínimo e máximo de resposta para cada amostra, fornecendo insights adicionais sobre a variabilidade do desempenho da aplicação;
  • Error %: Esta coluna exibe a porcentagem de amostras que resultaram em erro durante o teste. Isso é crucial para avaliar a estabilidade e a confiabilidade da aplicação sob carga;
  • Throughput: Esta coluna exibe o número de requisições por segundo processadas pelo servidor;
  • Received KB/sec e Sent KB/sec: Estas colunas exibem a quantidade de KBs por segundo recebidos e enviados, respectivamente, pela amostra durante o teste.

Executando os testes

Com o Thread Group, Sample e Listener configurados já é possível executar os testes e avaliar os resultados.

Para executar os testes, basta clicar no ícone de play na cor verde, localizado na barra de ícones abaixo da barra de menu superior, ou selecionar a opção Start no menu superior Run.

Antes de executar o teste vamos realizar uma mudança, para simular uma carga de uso maior. Nas configurações do Thread Group 500 usuários vamos alterar o campo “Name” para “15 mil usuários”, o campo “Number of Threads (users)” para “15000” e o campo “Loop count” para “3”.

Ou seja, nosso teste vai sumular 15 mil usuários disparando 3 requisições, totalizando 45 mil requisições, que é uma carga bem razoável:

Tela de configurações do Thread Group com o campo “Name” alterado para “15 mil usuários”, o campo “Number of Threads (users)” alterado para 15000 e o campo “Loop Count” alterado para 3.

Execute o teste e na sequência clique no Listener “Aggregate Report” para visualizar o resultado e analisar os números:

Tela do Listener Aggregate Report com a tabela exibindo os resultados do teste.

Lembre-se que esses valores não são fixos e podem variar a cada execução dos testes, além de também variar de acordo com o computador no qual foram executados.

Justamente por isso é importante realizar os testes em um ambiente parecido com o de produção, para que os valores sejam os mais realistas possíveis.

Analisando os resultados

Após executar os testes e obter os resultados nos Listeners configurados, é necessário realizar uma análise dos números para identificar possíveis gargalos e problemas de desempenho na aplicação.

Algumas etapas a serem seguidas e considerações a serem feitas durante essa análise são:

Revisão dos resultados

  • Analise as métricas gerais, como tempo médio de resposta, taxa de erro, throughput e taxa de transferência de dados;
  • Verifique se esses valores estão dentro das expectativas e se atendem aos requisitos de desempenho da aplicação.

Identificação de padrões

  • Procure por padrões nos dados, como picos de tempo de resposta, aumento repentino na taxa de erro ou redução na taxa de transferência;
  • Identifique se esses padrões estão associados a ações específicas da aplicação ou a determinadas condições de carga.

Análise por requisição

  • Analise individualmente as requisições feitas durante o teste, verificando seus tempos de resposta, taxas de erro e throughput;
  • Identifique quais requisições estão apresentando desempenho abaixo do esperado e investigue possíveis causas.

Comparação com execuções anteriores

  • Compare os resultados da execução atual com os de execuções anteriores para identificar tendências ou mudanças no desempenho da aplicação ao longo do tempo;
  • Verifique se houve melhorias ou regressões após alterações no código ou na infraestrutura da aplicação.

Identificação de gargalos

  • Procure por possíveis gargalos de desempenho, como recursos do servidor sobrecarregados, lentidão no processamento de requisições ou problemas de conexão com o banco de dados;
  • Priorize a resolução desses gargalos com base no impacto que têm no desempenho geral da aplicação.

Otimização e ajustes

  • Com base na análise dos resultados, faça ajustes no código, na configuração do servidor ou na infraestrutura da aplicação para melhorar o desempenho e resolver os problemas identificados;
  • Teste novamente após as otimizações para verificar se as mudanças tiveram o efeito desejado e se os problemas foram resolvidos.

Execução via linha de comandos

O JMeter oferece a possibilidade de executar os testes diretamente pela linha de comandos, algo que favorece a automatização do processo de execução dos testes.

Para executar os testes via linha de comando, basta seguir os passos a seguir:

  1. Abra o terminal ou prompt de comando;
  2. Navegue até o diretório bin do JMeter, onde está localizado o arquivo "jmeter";
  3. Execute o teste com o comando "jmeter" seguido do nome do arquivo de script do teste a ser executado. Por exemplo: jmeter -n -t Listagem de produtos.jmx.

O parâmetro "-n" indica que o teste será executado em modo não gráfico, ou seja, sem a interface gráfica do JMeter, e o parâmetro "-t" especifica o arquivo de script do teste a ser executado.

Durante a execução do teste, o JMeter exibirá os resultados diretamente no terminal ou prompt de comando, incluindo métricas de desempenho e status da execução.

Vantagens de executar os testes via linha de comandos

  • Integração com CI/CD: Esse modo facilita a integração do JMeter com sistemas de integração contínua (CI) e entrega contínua (CD), como Jenkins, Travis CI e GitHub Actions;
  • Escalabilidade e distribuição: É possível distribuir a carga de teste em vários servidores e máquinas virtuais, permitindo simular cargas de usuários mais realistas e escaláveis.

Outros cenários mais complexos

No artigo focamos os testes em uma requisição simples para um endpoint de uma API Rest, mas o JMeter é bastante versátil e permite realizar testes em cenários mais complexos.

Por exemplo, é possível simular fluxos que envolvam múltiplas requisições interdependentes, manipulação de dados e extração de informações para uso em requisições subsequentes.

Essa capacidade é muito útil para simular comportamentos reais dos usuários em aplicações Web, incluindo processos de autenticação e navegação em diferentes partes da aplicação.

Conclusão

A utilização do Apache JMeter proporciona uma abordagem abrangente e eficaz para a avaliação do desempenho de aplicações.

Ao realizar testes de performance, os times de desenvolvimento e QA podem identificar possíveis gargalos e problemas de escalabilidade antes mesmo da aplicação ser implantada no ambiente de produção.

Isso não apenas contribui para a melhoria contínua da qualidade do software, mas também para a satisfação dos usuários finais, garantindo uma experiência mais fluida e confiável.

Além disso, o JMeter oferece um boa flexibilidade para lidar com diferentes cenários de testes, desde requisições simples até simulações complexas de interações de usuários em aplicações Web.

Sua capacidade de execução via linha de comando e integração com sistemas de CI/CD o faz uma excelente ferramenta para a inclusão dos testes de performance em pipelines de desenvolvimento.

Referências

Caso você tenha interesse em aprofundar os estudos sobre testes, performance e otimização, recomendamos os seguintes materiais complementares:

Rodrigo da Silva Ferreira Caneppele
Rodrigo da Silva Ferreira Caneppele

Bacharel em Sistemas de Informação pela Universidade Católica de Brasília e programador desde 2005, com especialização em aplicações Web, APIs Rest, arquitetura e cibersegurança. Desde 2012 também atua como instrutor, produzindo e ministrando cursos de desenvolvimento de software.No YouTube, mantém o @canaldojavao, cujo foco é ensinar programação com Java e também outros assuntos relacionados com desenvolvimento de software.

Veja outros artigos sobre Programação