/test-performance

K6 é uma ferramenta para executar alguns tipos de teste de performance. A maneira de programar o teste é através da sintaxe do Javascript, porém toda sua engine é através de Golang, dada a desenvoltura de Go para execução com boa performance.

Primary LanguageJavaScript

K6 - Performance Test

Esta é uma documentação inicial sobre testes de performance com k6, baseada na documentação oficial. Para além de aprender a utilizar a ferramenta, a documentação do k6 é também um fonte para aprender sobre testes de performance.

K6 é uma ferramenta para executar alguns tipos de teste de performance. A maneira de programar o teste é através da sintaxe do Javascript, porém toda sua engine foi construída com Golang, dada a desenvoltura de Go para execução com boa performance. K6 é uma alternativa a ferramentas tradicionais, como por exemplo, o Jmeter que é uma ferramenta com interface gráfica que permite teste de performance.

Instalação

Sua instalação é simples, feita através de um binário que pode ser instalado nos principais sistemas operacionais e com Docker.

Segue a Documentação do k6:
Detalhes sobre a instalação do k6

Tipos de testes de performance que podemos fazer com k6.

  • Smoke tests valida se o sistema performa adequadamente acima da carga mínima.
  • Avarage-load test valida como o sistema performa acima das condições normais esperadas.
  • Stress tests valida como o sistema performa quando a carga excede o limite da sua capacidade média.
  • Soak tests valida como o sistema se recupera e performa sob um extenso período.
  • Spike tests valida o comportamento e a sobrevivencia do sistema em casos de aumentos repentinos, curtos ou massivo no tráfego de usuários.
  • Breakpoint tests consiste em gradativamente aumentar a carga para identificar o limite da capacidade do sistema.

Segue abaixo a tabela disponibilizada na documentação oficial do k6. Nela podemos ver resumidamente o tipo com a quantidade de usuários virtuais (VUs), a duração e contexto que podemos utilizar estes testes.

Tabela de resumo para cada tipo dos testes

obs: acesse cada tipo de teste da tabela abaixo e veja na documentação oficial como estão estruturados os testes no código.

TipoVUs (usuários virtuais)/ThroughputDuraçãoQuando?
SmokeBaixaCurta (segundos ou minutos)Quando ocorre uma alteração relevante no sistema e é necessário verificar se a lógica de uma funcionalidade importante foi impactada.
CargaMédia de produçãoMédia (5-60 minutos)Avalia se o sistema mantém a performance com a média de usuários em produção.
StressAlta (acima da média)Média (5-60 minutos)Quando o sistema irá receber um carga acima da média e é necessário ver como ele lida com isso.
SoakMédiaLonga (horas)Após alterações para verificar o sistema sob uso contínuo prolongado
SpikeMuito altaCurta (alguns minutos)Quando o sistema se prepara para eventos sazionais que receberá picos de tráfego
BreakpointAumentar até quebrarEnquanto for necessárioAlgumas vezes para encontrar os limites superiores do sistema

Fonte: k6 - Load test type - 2023.

Cada tipo de teste deve ser executado de acordo com o contexto da aplicação alinhado com as necessidades da equipe.


Tipos de testes e a relação entre número de usuários virtuais e tempo de execução.

image Fonte: k6 - Load test type - 2023.

Onde programar os tipos de testes

Cada um dos tipos de testes são configurados dentro da variável options. Vejamos abaixo como seria a configuração para cada tipo da tabela acima.

Smoke testing

export const options = {
  vus: 3, // Chave para Smoke test. Manter de 1 a 3 VUs, max 5 VUs
  duration: '1m', // Este tempo pode ser curto ou com apenas 1 iteração
};

Load testing

export const options = {
    // Chaves de configuração para teste de carga é nesta seção
  stages: [
    { duration: '5m', target: 100 }, // o táfego faz o movimento de ramp-up from saltando de 1 para 100 usuários em 5 minutos.
    { duration: '30m', target: 100 }, // mantém em 100 usuários por 10 minutos
    { duration: '5m', target: 0 }, // faz o movimento de ramp-down descendo de 100 para 0 usuários.
  ],
};

Stress testing

export const options = {
    // Chaves de configuração para testes de stress
  stages: [
    { duration: '10m', target: 200 }, // o trafego faz o movimento de ramp-up de 1 to  200 usuarios até 10 minutos.
    { duration: '30m', target: 200 }, // mantem 200 usuários por 10 minutos
    { duration: '5m', target: 0 }, // faz o movimento ramp-down descendo para 0 usuários.
  ],
};

Soak testing

export const options = {
    // Chaves de configuração para Teste Soak
  stages: [
    { duration: '5m', target: 100 }, // o táfego faz o movimento de ramp-up from saltando de 1 para 100 usuários em 5 minutos.
    { duration: '8h', target: 100 }, // mantém 100 usuários por 8 horas!!!
    { duration: '5m', target: 0 }, //  faz o movimento ramp-down descendo para 0 usuários.
  ],
};

Spike testing

export const options = {
    // Chaves de configuração para Teste Spike
  stages: [
    { duration: '2m', target: 2000 }, // repentino movimento de ramp-up com um pico de usuários (2000) em 2 minutos.
    // No plateau
    { duration: '1m', target: 0 }, // rapidamente faz o movimento de ramp-down 0 usuários.
  ],
};

Breakpoint testing

export const options = {
 // Chaves de configuração para breakpoint.
  executor: 'ramping-arrival-rate', // Garanta o aumento da carga se o sistema desacelerar
  stages: [
    { duration: '2h', target: 20000 }, // apenas aumente lentamente para uma carga ENORME
  ],
};

Como executar via CLI

  • Execução básica do teste deve informar o nome do arquivo que deve ser executado.
    k6 run script.js

  • Execucação acrescentando virtual users e duração do teste via CLI (vus)
    k6 run --vus 10 --duration 30s script.js

Análise das Metricas

As métricas no k6 aparecem na saída com o resultado dos testes, ao lado esquerdo dos valores.

metricas

Descrição das métricas: Detalhe das métricas

Valores das métricas

  • min = minima. O menor tempo de resposta de uma requisição.

  • max = maxima. O maior tempo de resposta de uma requisição.

  • avg = média. O total da soma de total as requisições dividida pela quantidade de requisições.

  • med = mediana. O valor real que está entre (ao meio) de todas as requisições.

  • p = percentil. O valor que atenda uma determinada porcentagem da amostra. Por exemplo: 90% dos usuários tiveram tempo de resposta de até 1.7 segundos.

Podemos também customizar as métricas: Custom Metrics
Exemplo de métricas customizadas: metricas customizadas

As métricas no K6 estão organizadas pelos seguintes tipos de métricas:

  • Conters soma de valores.
  • Gauges identifica o menor, o maior e o último valor.
  • Rates frequencia que um valor diferente de zero ocorre.
  • Trends é a porcentagem.

É atraveés deste tipos de métricas que podemos criar outras de maneira customizada. Como o exemplo do código dentro de thresholds-all.js.

Assertions (Checks)

Através dos checks no K6, podemos validar as respostas que esperamos para determinados cenários. Como por exemplo, tempo de resposta, quantidade de caracteres no response body, status code da requisição, conteúdo do response body, entre outras. Segue a documentação com mais exemplos:

Checks/Assertions

Thresholds

São critérios definidos que o teste deve cumprir durante a execução, em função de uma ou mais métricas definidas. Esses critérios que definirão se o teste passou ou falhou.

 trhesholds:{
      http_req_failed: ['rate<0.01'],
      http_req_duration: ['p(95)<200'],
    }

No exemplo acima, temos definido que para a metrica http_req_failed o cirtério de falha deve ser menor que 1% (threshold ['rate<0.01']). E para a métrica http_req_duration, o critério deve ser que 95% dos usuários devem obter o tempo de resposta da requisição menor que 200 ms (threshold ['p(95)<200']).

Definições de Threshold abaixo:

Threshold.

Opções de execução do teste

O K6 oferece diversas opções para organização do teste. Entre elas, temos a estrutura entre setup, teardown e default. Em setup, a função é executada apenas uma única vez na inicialização do teste. Equanto que teardown, é a execução em um única vez no final do teste. A função default, executa os testes.

Podemos verificar a ordenação acima em: opção de ordenação.

Outra maneira de ordenar o comportamento do teste, é através do arquivo config.json. Nele, definimos as stages, hosts, thresholds, etc. Ele deve ser colocado dentro do diretório loadimpact/k6/ . A configuração pode ser vista em config.js.
Para mais detalhes: default config path.

Mais opções: k6 options.

Browser (xk6) - Módulo experimental e passivel de alterações.

O k6 possibilita testes de performace no frontend. Além disso, podemos fazer testes híbridos, ou seja, articular dentro dos testes um fluxo que interaja backend e frontend. Pode ver sobre o primeiro caso, apenas com frontend no browser.js. O segundo caso, chamado de híbrido, pode ser conferido em hibrid.js.

Para executar os testes com o browser, precisamos setar a variável de ambiente $env:K6_BROWSER_ENABLED="true" .

Para mais detalhes e exemplos, podemos ver em: Browser Test .

Manifesto k6

O manifesto, é a maneira explicita em que os desenvolvedores da ferramenta argumentam o porquê acreditam na aplicação desta para testes de performance. Vejamos o seus pontos.

Um teste simples é melhor do que não testar.

  • Um teste de carga deve imitar o número de usuários e clientes o mais próximo possível do mundo real.

  • Inicie por um teste simples, sinta a segurança de que está obtendo algo com este teste. Depois disso, aumente a complexidade do teste até onde entender que não estará sendo um esforço alto para um retorno insuficiente.

  • Há dois tipos de organização de teste de carga. Eles podem ser 1) "unidade de teste de carga" e 2) "cenário de teste de carga".

    • Unidade de teste de carga, podemos começar com a verificação de performance para um endpoint em isolado.
    • Cenario de teste de carga, reproduz o tráfego no sistema de maneira consistenete mais próximo do que será encontrado no mundo real.
  • Teste de carga deve ser orientado a objetivos . Especificar os objetivos da performance é parte importante do que queremos com o teste de carga. Para isso, utilizar checks e thresholds importante para definir o que pode ou não falhar.

  • Os testes de carga devem iniciar do nosso ambiente local.