Pular para conteúdo

Testes de Carga

Testes de performance e carga da API do TepConfina com k6.

Framework

Ferramenta Versao Descricao
k6 0.50+ Ferramenta de testes de carga open-source

Estrutura dos Scripts

tests/load/k6/
  smoke.js        # Teste basico de sanidade
  load.js         # Teste de carga tipica
  stress.js       # Teste de estresse
  helpers/
    auth.js       # Helper de autenticacao
    config.js     # Configuracoes compartilhadas

Cenarios

Smoke Test

Verifica se a API responde corretamente sob carga minima.

Configuracao Valor
VUs 1
Duracao 30 segundos
// smoke.js
import http from 'k6/http';
import { check, sleep } from 'k6';
import { authenticate } from './helpers/auth.js';

export const options = {
  vus: 1,
  duration: '30s',
  thresholds: {
    http_req_duration: ['p(95)<500'],
    http_req_failed: ['rate<0.01'],
  },
};

export function setup() {
  return authenticate();
}

export default function (data) {
  const headers = { Authorization: `Bearer ${data.token}` };

  // Listar lotes
  const lotesRes = http.get(`${__ENV.BASE_URL}/api/lotes`, { headers });
  check(lotesRes, {
    'lotes status 200': (r) => r.status === 200,
    'lotes tem dados': (r) => JSON.parse(r.body).length > 0,
  });

  sleep(1);

  // Dashboard
  const dashRes = http.get(`${__ENV.BASE_URL}/api/dashboard`, { headers });
  check(dashRes, {
    'dashboard status 200': (r) => r.status === 200,
  });

  sleep(1);
}

Load Test

Simula carga tipica de uso em producao.

Configuracao Valor
VUs 20
Duracao 3 minutos
Ramp-up 30 segundos
Ramp-down 30 segundos
// load.js
import http from 'k6/http';
import { check, sleep } from 'k6';
import { authenticate } from './helpers/auth.js';

export const options = {
  stages: [
    { duration: '30s', target: 20 },  // ramp-up
    { duration: '2m', target: 20 },   // carga estavel
    { duration: '30s', target: 0 },   // ramp-down
  ],
  thresholds: {
    http_req_duration: ['p(95)<500'],
    http_req_failed: ['rate<0.01'],
  },
};

export function setup() {
  return authenticate();
}

export default function (data) {
  const headers = { Authorization: `Bearer ${data.token}` };

  // Fluxo: listar lotes -> detalhe -> pesagens
  const lotesRes = http.get(`${__ENV.BASE_URL}/api/lotes`, { headers });
  check(lotesRes, { 'lotes ok': (r) => r.status === 200 });

  const lotes = JSON.parse(lotesRes.body);
  if (lotes.length > 0) {
    const loteId = lotes[0].id;

    const detalheRes = http.get(
      `${__ENV.BASE_URL}/api/lotes/${loteId}`, { headers });
    check(detalheRes, { 'detalhe ok': (r) => r.status === 200 });

    const pesagensRes = http.get(
      `${__ENV.BASE_URL}/api/lotes/${loteId}/pesagens`, { headers });
    check(pesagensRes, { 'pesagens ok': (r) => r.status === 200 });
  }

  sleep(1);
}

Stress Test

Testa os limites da API sob carga extrema.

Configuracao Valor
VUs 50
Duracao 5 minutos
Ramp-up 1 minuto
Ramp-down 1 minuto
// stress.js
import http from 'k6/http';
import { check, sleep } from 'k6';
import { authenticate } from './helpers/auth.js';

export const options = {
  stages: [
    { duration: '1m', target: 50 },   // ramp-up agressivo
    { duration: '3m', target: 50 },   // carga maxima
    { duration: '1m', target: 0 },    // ramp-down
  ],
  thresholds: {
    http_req_duration: ['p(95)<1000'],
    http_req_failed: ['rate<0.05'],
  },
};

Cenarios Testados

Cenario Endpoints
Autenticacao POST /api/auth/login, POST /api/auth/refresh
Lotes CRUD GET /api/lotes, GET /api/lotes/:id, POST /api/lotes
Pesagens GET /api/lotes/:id/pesagens, POST /api/pesagens
Animais GET /api/lotes/:id/animais, POST /api/animais

Thresholds (Criterios de Aceite)

Metrica Smoke Load Stress
p(95) latencia < 500ms < 500ms < 1000ms
Taxa de erro < 1% < 1% < 5%
p(99) latencia < 1000ms < 1000ms < 2000ms

Helper de Autenticacao

// helpers/auth.js
import http from 'k6/http';

export function authenticate() {
  const res = http.post(`${__ENV.BASE_URL}/api/auth/login`,
    JSON.stringify({
      email: 'admin@tepconfina.com',
      password: 'Admin@123',
    }),
    { headers: { 'Content-Type': 'application/json' } }
  );

  return { token: JSON.parse(res.body).token };
}

Executando os Testes

# Smoke test
k6 run --env BASE_URL=http://localhost:5000 tests/load/k6/smoke.js

# Load test
k6 run --env BASE_URL=http://localhost:5000 tests/load/k6/load.js

# Stress test
k6 run --env BASE_URL=http://localhost:5000 tests/load/k6/stress.js

Ambiente de teste

Execute testes de carga apenas em ambientes de staging. Nunca execute em producao sem autorizacao.

Interpretando Resultados

     ✓ lotes ok
     ✓ detalhe ok

     http_req_duration...: avg=45ms  min=12ms  p(95)=120ms  p(99)=250ms
     http_req_failed.....: 0.00%
     http_reqs...........: 2400     40/s
     vus.................: 20       min=20  max=20
Metrica Descricao
http_req_duration Distribuicao de latencia
http_req_failed Percentual de requisicoes com falha
http_reqs Total de requisicoes e taxa por segundo
vus Usuarios virtuais simultanoes

Metricas customizadas

Use Trend, Counter e Rate do k6 para criar metricas especificas do negocio, como tempo de resposta por endpoint.