QANode Logo

Nó Load Test

O nó Load Test executa testes de carga e performance contra endpoints HTTP, simulando múltiplos usuários virtuais (VUs) em paralelo. Gera evidências visuais em PNG com métricas detalhadas e suporta critérios de aprovação automáticos via limiares.


Visão Geral

PropriedadeValor
Tipoload-test
CategoriaPerformance
Cor🟫 Âmbar (#92400E)
Entradain
Saídaout

Tipos de Teste

Cada tipo de teste gera um perfil de carga diferente automaticamente a partir dos campos VUs e Duração.

TipoDescriçãoQuando Usar
Smoke1 VU, duração configuradaValidar que o endpoint responde antes de rodar testes maiores
LoadRamp up → sustentação → ramp downVerificar comportamento sob carga normal esperada
StressRamp agressivo até o limiteIdentificar o ponto onde o sistema começa a degradar
SpikePico súbito de VUsTestar reação a picos repentinos de tráfego (ex: Black Friday)
SoakCarga sustentada por longa duraçãoDetectar memory leaks e degradação gradual
BreakpointEscada progressiva de VUsEncontrar o ponto exato de ruptura do sistema

Configuração

Requisição

CampoTipoDescrição
CredencialstringCredencial HTTP salva (preenche URL e auth automaticamente)
MétodostringGET, QUERY, POST, PUT, PATCH, DELETE, HEAD, OPTIONS
URLstringEndpoint alvo (suporta {{ }})
AuthstringTipo de autenticação manual (se não usar credencial)
HeadersobjectCabeçalhos adicionais da requisição
Parâmetros de QueryarrayPares chave-valor adicionados à URL
Tipo do CorpostringNenhum, JSON, Texto bruto, x-www-form-urlencoded, multipart/form-data ou Arquivo binário
Body / Campos / ArquivoanyConteúdo enviado conforme o tipo do corpo

Corpo da Requisição

O construtor de requisição do Load Test segue o mesmo modelo do nó HTTP Request:

TipoQuando usar
NenhumRequisições sem body
JSONAPIs REST que recebem objetos ou arrays JSON
Texto brutoXML, SOAP, payload textual ou formato customizado
x-www-form-urlencodedFormulários URL encoded
multipart/form-dataFormulários com campos de texto e arquivos
Arquivo binárioUpload direto do conteúdo de um fileRef no body

Campos de header e body aceitam expressões {{ }}. Para enviar arquivo, use um fileRef vindo de outro nó:

Arquivo: {{ steps["file-generate"].outputs.fileRef }}

Também é possível importar um comando curl; o QANode tenta converter método, URL, headers, query, body e campos de formulário para o modo visual correspondente.

Dados Dinâmicos por Requisição

A seção Dados dinâmicos gera valores novos imediatamente antes de cada requisição de cada usuário virtual. Ela é indicada para endpoints que exigem e-mail único, identificador externo, número sequencial, data futura ou outra informação que não pode ser repetida durante o teste.

Crie um valor na seção Dados dinâmicos e use-o com a sintaxe:

{{ load.nomeDoValor }}

Os valores podem ser usados em:

  • URL e parâmetros de query;
  • nomes e valores de headers;
  • corpo JSON ou texto bruto;
  • chaves e valores de x-www-form-urlencoded;
  • nomes e valores de campos textuais multipart/form-data.

O conteúdo de um arquivo binário não é modificado. Em multipart, somente o nome do campo e os campos de texto aceitam dados dinâmicos.

Valores nativos

Estes valores existem automaticamente e não precisam ser cadastrados:

ExpressãoValor
{{ load.runId }}ID da execução do QANode
{{ load.requestId }}Sequência global da requisição, começando em 1 e sem repetição entre VUs
{{ load.vuId }}Identificador do usuário virtual
{{ load.iteration }}Número da iteração dentro daquele VU
{{ load.timestamp }}Data e hora ISO geradas no momento da requisição

O mesmo valor é reutilizado em todos os lugares de uma única requisição. Na requisição seguinte, os valores gerados são renovados.

Exemplo:

URL: https://api.exemplo.com/orders/{{ load.requestId }}
Header X-Request-Id: {{ load.requestId }}
Body: { "requestId": "{{ load.requestId }}" }

URL, header e body receberão o mesmo requestId naquela chamada.

Tipos disponíveis

TipoConfiguraçãoResultado
UUIDApenas nomeUUID v4 novo por requisição
E-mailPrefixo e domínioE-mail único com token da execução e requestId
SequênciaInício e incrementoinício + (requestId - 1) × incremento
Número aleatórioMínimo, máximo e casas decimaisNúmero aleatório dentro do intervalo
ListaUm valor por linha; seleção aleatória ou sequencialUm item da lista por requisição
TimestampFormato, deslocamento e unidadeData atual, passada ou futura
TemplateTexto com outras expressões loadValor composto depois que os demais são gerados
UUID
Nome: externalId
Tipo: UUID
Uso: {{ load.externalId }}
E-mail
Nome: customerEmail
Tipo: E-mail
Prefixo: performance
Domínio: example.com
Uso: {{ load.customerEmail }}

O resultado segue este padrão e não se repete dentro da execução:

performance_tokenDaExecucao_142@example.com

Use um domínio reservado ou controlado pela empresa. Não use endereços reais em um teste que possa disparar e-mails.

Sequência
Nome: customerNumber
Início: 1000
Incremento: 5

As primeiras requisições produzirão 1000, 1005, 1010 e assim por diante, independentemente de qual VU as executar.

Número aleatório
Nome: amount
Mínimo: 10
Máximo: 100
Casas decimais: 2

São aceitas de 0 a 10 casas decimais. O valor máximo deve ser maior ou igual ao mínimo.

Lista
Nome: region
Valores:
  south
  north
  east
Seleção: Sequencial

No modo Sequencial, os itens são distribuídos em ciclos de acordo com o requestId, o que ajuda a equilibrar a carga. No modo Aleatório, qualquer item pode ser escolhido a cada requisição.

Timestamp

Formatos disponíveis:

FormatoExemplo
ISO2026-07-21T18:30:00.000Z
Unix1784658600 em segundos
Unix ms1784658600000 em milissegundos

O deslocamento aceita segundos, minutos, horas ou dias. Use valor positivo para o futuro e negativo para o passado.

Nome: expiresAt
Formato: ISO
Deslocamento: 2
Unidade: Horas
Template

Templates são processados depois dos outros dados dinâmicos e podem combiná-los:

Nome: customerKey
Template: customer-{{ load.customerNumber }}-{{ load.externalId }}
Uso: {{ load.customerKey }}

Exemplo completo — criação de usuário único

Cadastre:

NomeTipoConfiguração
emailE-mailprefixo performance, domínio example.com
externalIdUUID
planListabasic, pro, seleção sequencial
sequenceSequênciainício 1, incremento 1

Use no body:

{
  "email": "{{ load.email }}",
  "externalId": "{{ load.externalId }}",
  "plan": "{{ load.plan }}",
  "sequence": "{{ load.sequence }}",
  "requestId": "{{ load.requestId }}",
  "createdAt": "{{ load.timestamp }}"
}

Cada chamada cria um payload diferente, inclusive quando vários VUs executam ao mesmo tempo.

Regras dos nomes

  • devem começar com uma letra;
  • podem conter letras, números, _ ou $;
  • não podem se repetir;
  • não podem usar os nomes reservados runId, requestId, vuId, iteration ou timestamp.

O QANode valida referências desconhecidas antes de iniciar a carga. Se o body usar {{ load.customer }} sem que customer exista, a execução falhará com uma mensagem de configuração em vez de gerar requisições incorretas.

Boas práticas

  • use uma sequência quando precisar de distribuição previsível;
  • use lista sequencial para equilibrar regiões, planos ou categorias;
  • use UUID ou e-mail quando a API exigir unicidade;
  • planeje a limpeza dos registros criados pelo teste;
  • lembre que dados dinâmicos alteram os inputs, mas não substituem limiares e análise das métricas;
  • faça um Smoke Test antes da carga completa para validar o formato gerado.

Configuração de Carga

CampoTipoPadrãoDescrição
VUsnumber10Número de usuários virtuais simultâneos
Duração (s)number30Duração total do teste em segundos
Think Time (ms)number0Pausa entre requisições de cada VU
Timeout (ms)number30000Tempo máximo de espera por resposta

Para o tipo Smoke, o campo VUs é fixo em 1 e não é exibido. Para o tipo Soak, o padrão de duração é 1800s (30 min). Para o tipo Breakpoint, o campo VUs representa o máximo de VUs que serão atingidos.

Como o Breakpoint funciona

O teste divide a duração total em passos de ~30s, aumentando os VUs progressivamente:

VUs: 10 | Duração: 60s  →  2 passos de 30s
  Passo 1: 0s → 30s  →  5 VUs
  Passo 2: 30s → 60s →  10 VUs

Stages Customizadas

Ative Custom na seção Stages para definir manualmente o perfil de carga:

CampoDescrição
Duração (s)Duração desta stage em segundos
Target VUsNúmero de VUs ao final desta stage

Exemplo de stages para um teste stress manual:

DuraçãoTarget VUsDescrição
30s10Ramp up inicial
60s50Carga sustentada
30s100Stress
15s0Ramp down

Autenticação

Usando Credenciais Salvas

Selecione uma credencial do tipo HTTP/API. A URL base e os dados de autenticação são aplicados automaticamente:

  1. Selecione a credencial no campo Credencial
  2. A URL base é preenchida automaticamente no campo URL
  3. Complete com o path do endpoint: /api/checkout

Autenticação Manual

TipoCamposResultado
Bearer TokenTokenHeader Authorization: Bearer {token}
Basic AuthUsuário + SenhaHeader Authorization: Basic {base64}
API KeyHeader Name + TokenHeader customizado com o token

Limiares (Thresholds)

Limiares definem critérios de aprovação automáticos. Se qualquer limiar não for atingido, o nó é marcado como FALHOU.

MétricaDescrição
p50Percentil 50 de latência (ms)
p95Percentil 95 de latência (ms)
p99Percentil 99 de latência (ms)
avgDurationLatência média (ms)
errorRateTaxa de erros (%)
rpsRequisições por segundo
OperadorSignificado
<Menor que
Menor ou igual
>Maior que
Maior ou igual

Exemplos de limiares comuns:

LimiarSignificado
p95 < 50095% das respostas em menos de 500ms
errorRate < 1Taxa de erro menor que 1%
rps > 10Mínimo de 10 requisições por segundo
p99 < 200099% das respostas em menos de 2s

Sem limiares configurados, o nó sempre passa (desde que o endpoint responda).


Outputs

OutputTipoDescrição
passedbooleantrue se todos os limiares foram atingidos
testTypestringTipo de teste executado
metricsobjectMétricas consolidadas do teste
thresholdsarrayResultado de cada limiar configurado
stagesarrayStages executadas (auto ou customizadas)

Estrutura do objeto metrics

{
  "totalRequests": 1141,
  "errorCount": 0,
  "errorRate": 0.0,
  "rps": 34.49,
  "avgDuration": 212,
  "minDuration": 98,
  "maxDuration": 668,
  "p50": 182,
  "p90": 332,
  "p95": 451,
  "p99": 579
}

Acessando os Outputs

// Verificar se passou
{{ steps["load-test"].outputs.passed }}  →  true

// Total de requisições
{{ steps["load-test"].outputs.metrics.totalRequests }}  →  1141

// Latência p95
{{ steps["load-test"].outputs.metrics.p95 }}  →  451

// Taxa de erro
{{ steps["load-test"].outputs.metrics.errorRate }}  →  0.0

// RPS
{{ steps["load-test"].outputs.metrics.rps }}  →  34.49

Evidências Geradas

O nó gera automaticamente dois gráficos PNG como evidência da execução:

1. Relatório de Resumo (load-test-report.png)

Visão consolidada com:

  • Cards de métricas (p50, p95, p99, Avg, RPS, Requests, Errors, Error Rate)
  • Gráfico de barras horizontais com distribuição de latência
  • Gráfico de throughput ao longo do tempo (req/s)
  • Pills de status de cada limiar configurado
  • Rodapé com stages executadas

2. Timeline RPS × Latência (load-test-timeline.png)

Gráfico dual-axis com:

  • Barras azuis (eixo esquerdo): RPS ao longo do tempo
  • Linha laranja (eixo direito): Latência média ao longo do tempo
  • Linha roxa tracejada (eixo direito): Latência p95 ao longo do tempo

O gráfico de timeline é especialmente útil para Breakpoint e Stress, onde é possível visualizar exatamente em que momento a latência começa a subir em resposta ao aumento de carga.


Exemplos Práticos

Smoke test — Validação básica

Tipo: Smoke
URL: https://api.exemplo.com/health
Método: GET
Duração: 10s

Ideal para rodar no início de um fluxo de testes — garante que o ambiente está no ar.

Load test — Carga normal com limiares

Tipo: Load
URL: https://api.exemplo.com/products
Método: GET
VUs: 20
Duração: 60s
Limiares:
  - p95 < 500
  - errorRate < 1

Stress test — Limites do sistema

Tipo: Stress
URL: https://api.exemplo.com/checkout
Método: POST
VUs: 100
Duração: 120s
Body: { "productId": "123", "quantity": 1 }
Auth: Bearer → {{ variables.API_TOKEN }}
Limiares:
  - p99 < 2000
  - errorRate < 5

Upload sob carga

Tipo: Load
URL: https://api.exemplo.com/upload
Método: POST
Tipo do Corpo: multipart/form-data
Campo arquivo:
  file = {{ steps["file-generate"].outputs.fileRef }}
VUs: 10
Duração: 60s
Limiares:
  - p95 < 1000
  - errorRate < 1

Use esse padrão para validar endpoints que recebem anexos, documentos ou imagens.

Breakpoint — Ponto de ruptura

Tipo: Breakpoint
URL: https://api.exemplo.com/search
Método: GET
Max VUs: 200
Duração: 300s
Limiares:
  - p95 < 1000
  - errorRate < 2

O sistema irá aumentar progressivamente de 1 até 200 VUs em passos de ~30s. Quando p95 ultrapassar 1000ms ou erros superarem 2%, o nó marca como falha — indicando o ponto de ruptura.

Encadeando com outros nós

[Load Test: Smoke]
    │ outputs.passed = true
    ▼
[If: {{ steps.smoke.outputs.passed }}]
    │ true  → [Load Test: Load completo]
    │ false → [Log: "Smoke falhou — ambiente indisponível"]

Isolamento de Fila

O nó Load Test é executado em uma fila separada (qanode-load-tests) para não interferir nos outros fluxos em execução.

Para configurar um worker dedicado ao Load Test:

WORKER_QUEUES=load-tests node dist/start.js

Para um worker que processa ambas as filas:

WORKER_QUEUES=executions,load-tests node dist/start.js

Dicas

  • Comece pelo Smoke antes de rodar testes de carga — garante que o endpoint está respondendo corretamente
  • Configure limiares para que o teste falhe automaticamente quando o sistema degradar, sem precisar analisar os números manualmente
  • Use o gráfico de timeline para identificar o momento exato de degradação em testes Breakpoint e Stress
  • Think Time simula comportamento humano — útil para testes Soak onde você quer carga contínua mas realista
  • Credenciais salvas facilitam a execução em diferentes ambientes (staging, produção) sem alterar o fluxo
  • Para testes confiáveis, até 100 VUs por instância de worker. Acima disso, considere um worker dedicado