Testes de carga para API com Gatling (1)

Hugo Pereira Silva
beyondTest
Published in
7 min readJun 9, 2020

--

Esse artigo esta relacionado a uma série de futuros posts para testes de performance em api utilizando o Gatling, em primeiro momento a real intenção era criar um único post abordando nossa experiência em uma empresa que trabalhamos, porém o conteúdo se tornou muito exaustivo para explicar em um único post. Portanto resolvemos fragmentar em uma serie explicando desde o básico até um caso de uso semelhante ao que vivenciamos que foi muito gratificante.

Antes de começarmos, vamos entender as diferenças..

Stress testing

Load testing

Performance testing

Para isso recomendo a leitura deste outro post que escrevi a diferença entre cada um dos testes citados acima: Uma breve introdução sobre testes de Performance, Stress e Carga

Existem muitas ferramentas de teste, então porque escolhemos Gatling? Uma das justificativas é que essa ferramenta proporciona uma grande flexibilidade, como ele trabalha com DSL facilita bastante a escrita dos cenários, ao mesmo tempo é possível acoplar classes e códigos de origem JVM e ganhar liberdade de implementar algumas facilidades da linguagem. O Gatling foi apresentado por um gestor como possível substituto para o Jmeter na ocasião.

Puts, mas o que é o Gatling?

Gatling é uma ferramenta open source de teste não funcional de carga, baseada em Scala, Akka e Netty e tem como principal facilidade a escrita de cenários em DSL.

Link para documentação: https://gatling.io/docs

Bom vamos começar.

Existem muitas outras formas de utilizar o Gatling, através do binário ou através de gerenciadores de dependências como Gradle ou Maven.

Vou explicar usando o Gradle, mas nada impede de usar outras formas, segue abaixo os links dos projetos com cada uma das formas:

Maven> https://github.com/gatling/gatling-maven-plugin-demo

Gradle> https://github.com/lkishalmi/gradle-gatling-plugin

Binário> https://gatling.io/open-source

Bom antes de começar precisamos instalar algumas dependências.

Pré-requisitos:

1. Java (JDK 8 ou superior)
2. IDE de desenvolvimento (Intellij, Eclipse etc…)
3. E na IDE é necessário a instalação do plugin do Scala.

Cumprindo esses pré-requisitos vamos abrir a IDE e usar nosso projeto como referência: Código do projeto

Ao abrir o projeto é muito possível que o plugin seja identificado pela IDE e peça para instalar logo em sequencia. Se isso não ocorrer abra (Preferencias>Plugins>(Procurar por Scala)

Antes de usar o projeto

Peço para que no momento de testar o uso da ferramenta direcione o endpoint do serviço para um local que permita esse tipo de teste, sugiro levantar um serviço local e apontar para o mesmo. Existe um artigo do Eduardo Pacheco Celeste ensinando a subir um mock service que pode auxiliar muito nessa primeira etapa de construção do teste.

Link> Criando-uma-rest-api-fake-com-json-server

Esse teste foi criado apontando para um mock service online com apenas duas requisições paralelas, sem intuito de comprometer o serviço.

Explicando o Projeto

No momento que clonar o projeto e abrir no Intellij vai será possível enxergar a seguinte estrutura.

Vamos tentar detalhar as pastas e arquivos mais importantes:

Pasta config contém as informações de configuração do Gatling como por exemplo a conexão com banco de dados em série, locais de resources e configuração de reports e etc. Essa parte não vai ser explorada nesse momento, porém em um post futuro iremos entender mais sobre as possíveis configurações.

Vamos continuar e observar o nosso build.gradle, ele está bem simplificado, possui os plugins, dependências e por último a task para execução do teste.

Dentro do diretório src/test/scala/simulations podemos encontrar nosso script de teste. Vamos observar como ele está configurado.

O código acima é praticamente dividido em 3 partes:

Configuração da Request (url e header)

Nessa etapa criamos dois valores imutáveis para configuração, o primeiro definimos a nossa Url que será incorporada nas requisições abaixo como default. No segundo bloco temos a configuração do header que é montado como um map de strings.

Configuração do cenário de requests

Aqui temos dois tipos de blocos de requests, um de GET e um outro de POST. A estrutura do método GET foi declarada com um valor imutável que vai receber a requisição construída em DSL. Definimos como nome do cenário o valor “Exemplo de request get”, e logo em seguida temos um comando exec(), que recebe um nome e tem a função de executar uma ação do tipo http, mas que poderia ser qualquer um desses protocolos(HTTP, LDAP, POP, IMAP, etc). Continuando temos o método dessa ação que é o GET, nesta parte poderíamos informar o caminho completo da página, mas como definimos antes a URL base do projeto só precisamos informar o path final. Na última linha do bloco de get temos uma adição de um header novo dentro da estrutura do teste.

Na estrutura do POST, temos algumas diferenças como por exemplo o da inclusão do header declarado no começo do teste sentHeaders e logo abaixo o StringBody. Nessa etapa do body existem outras abordagens, como a leitura de payloads externos ou inclusão de variáveis no corpo que também serão abordadas em outros posts.

SetUp que faz a ação de tráfego (Post e Get)

Na parte de setUp temos a chamada de ambos os valores imutáveis dos cenários que serão executados, nessa parte podemos criar o comportamento desejado para simular o tráfego em nosso teste. Veremos nos próximos posts uma combinação para cada um dos cenários de testes exemplificados anteriormente. No caso do exemplo acima, para cada um dos cenários está apenas simulando um único usuário.

Vamos rodar esse teste!!!

Vamos rodar utilizando o comando da task do gradle. Navegue ate o diretório raiz do projeto e digite. Talvez seja necessário dar permissão para o arquivo gradlew, se sim execute o primeiro comando.

$ chmod +x gradlew $ gradlew runLoadtest

Apos executar esse comando o gatling irá mostrar o output no próprio terminal.

Simulation simulations.DemoSimulation started...====================================================================
2020-06-02 20:17:21 0s elapsed
---- Requests ------------------------------------------------------
> Global (OK=2 KO=0 )
> Saudacoes Get (OK=1 KO=0 )
> Saudacoes Post (OK=1 KO=0 )
---- Exemplo de request post ---------------------------------------
[##############################################################]100%
waiting: 0 / active: 0 / done: 1
---- Exemplo de request get ----------------------------------------
[##############################################################]100%
waiting: 0 / active: 0 / done: 1
====================================================================
Simulation simulations.DemoSimulation completed in 0 seconds
Parsing log file(s)...
Parsing log file(s) done
Generating reports...
====================================================================
---- Global Information --------------------------------------------------------
> request count 2 (OK=2 KO=0 )
> min response time 749 (OK=749 KO=- )
> max response time 749 (OK=749 KO=- )
> mean response time 749 (OK=749 KO=- )
> std deviation 0 (OK=0 KO=- )
> response time 50th percentile 749 (OK=749 KO=- )
> response time 75th percentile 749 (OK=749 KO=- )
> response time 95th percentile 749 (OK=749 KO=- )
> response time 99th percentile 749 (OK=749 KO=- )
> mean requests/sec 2 (OK=2 KO=- )
---- Response Time Distribution ------------------------------------
> t < 800 ms 2 (100%)
> 800 ms < t < 1200 ms 0 ( 0%)
> t > 1200 ms 0 ( 0%)
> failed 0 ( 0%)
====================================================================

De uma forma simples vamos explicar.

Nesse primeiro bloco temos um resumo das requisições, se ela receber um status code positivo ela cai no bloco de OK, o label Global é a soma dos requests.

Já na segunda parte temos um report agregado

Iniciando com a duração por tempo do teste, e abaixo valores de min, max, linhas de percentagem e percentagem de falhas. Veremos esses dados mais adiante em futuros posts.

Após esse teste ele também cria um diretório para o relatório final do teste, por default é criado na raiz com o nome da pasta chamada results, dentro deste diretório é criado outras pastas para cada execução.

Dentro de cada pasta de resultados existe um relatório que pode ser lido a partir de um arquivo .html. Nesse arquivo ele traz informações detalhadas e mais completas do que o report gerado no terminal.

Bom, vamos continuar a amadurecer nossos testes em posts futuros, e qualquer dúvida e só chamar.

Referências:

--

--