Utilizando Stackspot na criação de testes de performance com K6🏋️‍♂️
Tags: testing, k6, performance, stackspot
Published: 2023-05-04 23:50:13

Um dos principais pontos que destaco no [curso de testes de performance com K6](https://www.udemy.com/course/teste-de-performance-com-k6/?referralCode=95CCD8BC9F22A2A96BDA) é a simplicidade com que podemos criar testes do zero. O K6 segue um ciclo de vida padronizado, no qual todas as fases necessárias para executar um teste de performance precisam ser definidas. 

Logo, podemos utilizar de recursos que possibilitem a definição dessas fases do ciclo de vida em um script, acelerando o processo de criação e replicação para novos testes.

Neste artigo, abordaremos como criar scripts de testes de performance de forma automatizada com a ajuda de um plugin da StackSpot. 

## Entendendo o ciclo de vida do K6📚
Ao contrário de outras ferramentas de teste de performance, como o JMeter, o K6 segue um ciclo de vida bem definido. Isso significa que, independentemente da quantidade de vezes que o script de testes de performance seja executado, ele sempre passará pelas mesmas fases, na mesma ordem, sendo as fases de: 
- Inicialização
- Configuração
- Execução
- Desmontagem

### Inicialização
Durante a fase de inicialização do ciclo de vida do K6, ocorre o carregamento de arquivos locais e a importação de módulos nativos ou remotos. É importante ressaltar que essa chamada é feita apenas uma vez por VU. 

Um dos principais módulos nativos utilizados na criação de um script é o modulo http: 

```
import http from 'k6/http';
```

### Configuração
Durante a fase de configuração, são definidos os dados que serão compartilhados entre todas as VUs. Esses dados incluem informações cruciais, como a quantidade de VUs, duração, limites de validação e outras definições importantes para a execução do teste de performance. É importante destacar que essa fase é realizada apenas uma única vez durante todo o ciclo de vida.

```
export const options = {
  vus: 1,
  duration: '1m',
};
```

### Execução
Durante a etapa de execução, a função de teste é executada repetidamente com base nas configurações definidas anteriormente. Nesta fase, as VUs realizam solicitações HTTP, emitem métricas e executam validações e verificações definidas na fase de configuração. 

A principal característica que diferencia essa etapa das outras funções que podem ser definidas na fase de configuração, é que a função de execução é a definida como `default`. Isso significa que, mesmo que nenhuma outra função seja definida na fase de configuração, a função de execução será executada automaticamente com base nas configurações.

```
export default function () {
  http.get('https://test.k6.io');
}
```

### Desmontagem
Essa é uma etapa opcional, na qual podemos processar os resultados obtidos durante as fases de configuração e execução. É bastante útil quando queremos enviar resultados por webhook para uma plataforma externa, notificar determinados serviços, ou montar relatórios personalizados, pois recebe como parâmetro os resultados obtidos na fase de execução. Essa etapa é executada uma única vez durante todo o ciclo de vida do teste.

```
export function teardown(data) {
  console.log(JSON.stringify(data));
}
```

## Mão na massa👩‍💻

### Pré-requisito📑
- [K6](https://k6.io/docs/get-started/installation/)
- [Stackspot CLI](https://docs.stackspot.com/docs/stk-cli/installation/).

### Importando nossa stack 🔨
Para fins didáticos, utilizaremos a stack `qa-api-stack`, que já foi abordada em outros posts sobre o assunto Stackspot.

Para realizar a instalação, basta utilizar o seguinte comando na sua CLI: 

```
stk import stack https://github.com/marlo2222/qa-api-stack
```

> Importante: Essa é uma stack para fins didáticos e que seu principal objetivo, que é a configuração de testes de API, ainda está em desenvolvimento.

Podemos verificar a disponibilidade do plugin `k6-script-plugin`, executando o comando `stk list plugin`:

```
+------------------+-----------------------------------------------------------------+-----------------+
| name             | description                                                     | version(latest) |
+------------------+-----------------------------------------------------------------+-----------------+
| k6-script-plugin | Plugin para criação de scripts de testes de performance com k6. | Sem release     |
|                  |                                                                 |                 |
| pitest-java      | Plugin para a configuração de testes de mutação com a           | Sem release     |
|                  | ferramenta pitest em projetos java.                             |                 |
+------------------+-----------------------------------------------------------------+-----------------+
```

### Utilizando o plugin🔌

Antes de iniciarmos a criação dos nossos scripts de teste de performance, vamos criar um diretório chamado "testes-performance" com o comando `mkdir testes-performance`. Em seguida, entraremos no diretório recém-criado com o comando `cd testes-performance`.

Estando no diretório, podemos utilizar nosso plugin para criação de testes de performance com o seguinte comando:

```
stk apply plugin -s qa-api-stack/k6-script-plugin
```
> o argumento -s basicamente ignora a checagem de aplicativos que não foram criados utilizando Stackspot.

A Stackspot solicitara algumas informações para criação do script, sendo o primeiro ponto o nome do script, nesse exemplo informaremos _teste-get_:

```
? Informe o nome do script: teste-get
```
A seguir, precisamos configurar a quantidade de VUs que será utilizado no teste de performance. Neste caso, definiremos o valor de 50 VUs:
```
Informe a quantidade de VUs: 50
```

> As VUs (Virtual Users) representam a quantidade de usuários que simularemos acessar a nossa aplicação durante os testes de performance. 

Outra informação que precisamos configurar é a duração dos testes, que é expressa em segundos. Neste caso, definiremos a duração de 15 segundos.

```
Informe a duração em seg: 15
```
Um dos pontos mais importantes na configuração do nosso script de teste de performance é definir a URL que será utilizada para realização das requisições. Neste exemplo, usaremos uma API pública do K6, que retorna uma lista dos crocodilos atualmente cadastrados na plataforma.

```
Informe a url para teste: https://test-api.k6.io/public/crocodiles/
```

Assim como a URL para testes, precisamos informar o método HTTP que será utilizado para as requisições. O plugin está configurado para exibir uma lista com os principais métodos: GET, POST, PUT, DELETE. Nesse exemplo, selecionaremos a opção GET:

```
? Selecione o método de teste 
 » 1) get
   2) post
   3) put
   4) delete
```

A seguir, é necessário informar qual status code esperamos que as requisições retornem. Por padrão, o script utiliza o status code `200`. No entanto, é possível fornecer qualquer código de status valido.

```
? informe o status code esperado: 200
```
A próxima pergunta definira se você deseja adicionar alguns limites para validação do seu teste. Caso opte pela opção "Y", a Stackspot seguirá com algumas solicitações para definir esses limites. Neste exemplo, escolheremos a opção "Y".

```
Gostaria de definir thresholds/limites ao teste? (y/N) Yes
```

Primeiro, precisaremos definir um percentil de confiança para o limite que avalia a _duração das requisições_, vamos selecionar a opção 95%: 

```
? Selecione o percentil de confiança para duração da requisição 
   1) 90
 » 2) 95
```
Após definimos o intervalo de confiança para o indicador de _duração das requisições_, precisamos informar um tempo esperado em milissegundos(ms). Informaremos um tempo aproximado de 400 ms:

```
? Informe a duração esperada da requisição em ms: 400
```
> Ao definir o percentil de 95%, esperamos que 95% das nossas requisições tenham um tempo de resposta igual ou inferior a 400 ms. Se o intervalo de confiança não for atingido, o teste falhará.

O segundo critério que será avaliado será a taxa de requisições com sucesso. Também utilizaremos percentis para esse indicador. Nesse exemplo selecionaremos a opção de 99%:

```
? Selecione a taxa de sucesso para as requisições em %
   1) 90
   2) 95
 » 3) 99
```
> Para o nosso segundo indicador, esperamos que 99% das requisições retornem o código de status 200. Se o intervalo de confiança não for atingido, o teste falhará.

Podemos observar que a Stackspot nos informa que o plugin foi aplicado com sucesso:

```
Plugin qa-api-stack/k6-script-plugin aplicado.
```
  
Ao executar o comando ls, podemos verificar que o nosso script foi criado com sucesso.

```
$ ls
teste-get.js
```
### Analisando o script gerado🧐
Utilizando o comando `cat test-get.js` podemos observar a estrutura do script gerado pela Stackspot:

```
import http from 'k6/http';
import {sleep, check} from 'k6';

export const options = {
    vus: 50,
    duration: '15s',
    thresholds: {
        checks: ['rate > 0.99'],
        http_req_duration: ['p(95) < 400']
    }
}

export default function(){

    const params = {
        headers: {
            'Content-Type': 'application/json'
        }
    }

    const res = http.get('https://test-api.k6.io/public/crocodiles/', params);

    check(res,{
        'status 200': (r) => r.status === 200
    });

    sleep(1);
}
```
Podemos perceber que o nosso teste de performance foi dividido em três fases distintas:
- Inicialização: com a importação dos módulos necessários para o teste.
- Configuração: com a configuração de quantidade de vus, duração e limites no escopo da constante _options_.
- Execução: com o escopo da função _default_ que realiza a execução do nosso teste de performance.

É importante destacar que a fase de desmontagem é opcional e, por isso, optamos por não defini-la. No entanto, é possível parametrizar essa fase utilizando a Stackspot, caso necessário.

### Executando nosso teste🏆
Agora chegamos à fase mais esperada deste tutorial, a execução do nosso teste de performance. Podemos utilizar o seguinte comando: 

```
 k6 run teste-get.js
```

E obteremos como resultado a seguinte saída:

```
          /\      |‾‾| /‾‾/   /‾‾/
     /\  /  \     |  |/  /   /  /
    /  \/    \    |     (   /   ‾‾\
   /          \   |  |\  \ |  (‾)  |
  / __________ \  |__| \__\ \_____/ .io

  execution: local
     script: teste-get.js
     output: -

  scenarios: (100.00%) 1 scenario, 50 max VUs, 45s max duration (incl. graceful stop):
           * default: 50 looping VUs for 15s (gracefulStop: 30s)


     ✓ status 200

   ✓ checks.........................: 100.00% ✓ 668       ✗ 0
     data_received..................: 831 kB  52 kB/s
     data_sent......................: 119 kB  7.4 kB/s
     http_req_blocked...............: avg=23.06ms  min=0s      med=0s       max=310.93ms p(90)=0s       p(95)=306.61ms
     http_req_connecting............: avg=6.99ms   min=0s      med=0s       max=98.96ms  p(90)=0s       p(95)=92.33ms
   ✓ http_req_duration..............: avg=138.29ms min=84.38ms med=101.89ms max=871.45ms p(90)=179.46ms p(95)=330.96ms
       { expected_response:true }...: avg=138.29ms min=84.38ms med=101.89ms max=871.45ms p(90)=179.46ms p(95)=330.96ms
     http_req_failed................: 0.00%   ✓ 0         ✗ 668
     http_req_receiving.............: avg=448.18µs min=0s      med=0s       max=15.44ms  p(90)=471.4µs  p(95)=2.73ms
     http_req_sending...............: avg=5.07µs   min=0s      med=0s       max=510.4µs  p(90)=0s       p(95)=0s
     http_req_tls_handshaking.......: avg=9.07ms   min=0s      med=0s       max=125.65ms p(90)=0s       p(95)=120.03ms
     http_req_waiting...............: avg=137.84ms min=84.21ms med=101.82ms max=870.49ms p(90)=179.46ms p(95)=330.06ms
     http_reqs......................: 668     41.461698/s
     iteration_duration.............: avg=1.16s    min=1.08s   med=1.11s    max=2.18s    p(90)=1.2s     p(95)=1.64s
     iterations.....................: 668     41.461698/s
     vus............................: 7       min=7       max=50
     vus_max........................: 50      min=50      max=50
```
Podemos notar que os limites que definimos para a _http_req_duration_ e o _status code_ das solicitação foram validados com sucesso. É importante destacar que o indicador _iterations_ aponta para uma taxa de transferência de `41,46` solicitações por segundo, o que é bastante satisfatório para um ambiente de testes executado localmente.

### Conclusão💖

Neste artigo, realizamos a parametrização de algumas informações do nosso teste de performance. No entanto, há muitas outras a serem parametrizadas, como os parâmetros de headers, o payload request para as requisições, a leitura de arquivos externos, entre outras possibilidades.

Com a parametrização dessas informações, nosso script pode se tornar ainda mais flexível e adaptável às necessidades do nosso teste de performance.

Fica claro a flexibilidade que a Stackspot nos proporciona para resolvermos ou acelerarmos pontos relacionados ao processo de teste de software.

Deixo aqui o convite para você criar o seu próprio script utilizando esse plugin.😎

Sinta-se à vontade para qualquer questionamento, dúvida ou mesmo contribuição!😀

📩 [linkedin](https://www.linkedin.com/in/marlo-henrique-84a940109/)
🐱‍👤 [github](https://github.com/marlo2222)

> Quer sabe mais sobre Stackspot? vou esta deixando o link para o github oficial onde você pode encontrar os principais contatos para o [time da Stackspot](https://github.com/stack-spot).✨