Tipos de Teste de Carga
Load Testing
Verifica comportamento sob carga esperada.
Carga: 1000 usuários simultâneos
Duração: 30 minutos
Métrica: P95 < 500ms
Stress Testing
Vai além dos limites normais.
Carga: 1000 → 2000 → 5000 usuários
Objetivo: Encontrar ponto de quebra
Spike Testing
Picos súbitos de carga.
Normal: 500 usuários
Spike: 5000 usuários em 5 segundos
Recovery: 500 usuários
Soak Testing
Carga sustentada por longo período.
Carga: 1000 usuários
Duração: 8 horas
Objetivo: Memory leaks, degradação
k6 – Modern Load Testing
Instalação
# macOS
brew install k6
# Linux
sudo apt install k6
# Windows
choco install k6
Script Básico
// load-test.js
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
stages: [
{ duration: '2m', target: 100 }, // Ramp-up
{ duration: '5m', target: 100 }, // Steady
{ duration: '2m', target: 200 }, // Stress
{ duration: '5m', target: 200 }, // Steady
{ duration: '2m', target: 0 }, // Ramp-down
],
thresholds: {
http_req_duration: ['p(95)<500'], // 95{6727d158e4474b0847515bd23a8ee4bebd5f1aac7a18bc968e51d8985dccb442} < 500ms
http_req_failed: ['rate<0.01'], // < 1{6727d158e4474b0847515bd23a8ee4bebd5f1aac7a18bc968e51d8985dccb442} errors
checks: ['rate>0.95'], // > 95{6727d158e4474b0847515bd23a8ee4bebd5f1aac7a18bc968e51d8985dccb442} checks pass
},
};
const BASE_URL = 'https://api.exemplo.com';
export default function () {
// Login
const loginRes = http.post(${BASE_URL}/auth/login, {
email: 'user@example.com',
password: 'password123',
});
check(loginRes, {
'login status 200': (r) => r.status === 200,
'has token': (r) => r.json('token') !== undefined,
});
const token = loginRes.json('token');
// Get products
const productsRes = http.get(${BASE_URL}/products, {
headers: { 'Authorization': Bearer ${token} },
});
check(productsRes, {
'products status 200': (r) => r.status === 200,
'has products': (r) => r.json('items').length > 0,
});
sleep(1);
}
Cenários Complexos
// scenarios.js
import http from 'k6/http';
import { check, group } from 'k6/http';
import { Rate, Trend } from 'k6/metrics';
const errorRate = new Rate('errors');
const apiLatency = new Trend('api_latency');
export const options = {
scenarios: {
// Smoke test
smoke: {
executor: 'constant-vus',
vus: 10,
duration: '1m',
tags: { test_type: 'smoke' },
},
// Load test
load: {
executor: 'ramping-vus',
startVUs: 0,
stages: [
{ duration: '2m', target: 100 },
{ duration: '5m', target: 100 },
{ duration: '2m', target: 0 },
],
tags: { test_type: 'load' },
},
// Stress test
stress: {
executor: 'ramping-arrival-rate',
startRate: 1,
timeUnit: '1s',
preAllocatedVUs: 100,
maxVUs: 500,
stages: [
{ duration: '2m', target: 10 },
{ duration: '5m', target: 50 },
{ duration: '2m', target: 100 },
{ duration: '1m', target: 0 },
],
tags: { test_type: 'stress' },
},
// Spike test
spike: {
executor: 'ramping-vus',
startVUs: 0,
stages: [
{ duration: '30s', target: 100 },
{ duration: '1m', target: 1000 }, // Spike!
{ duration: '30s', target: 1000 },
{ duration: '2m', target: 0 },
],
tags: { test_type: 'spike' },
},
},
};
export default function () {
const res = http.get('https://api.exemplo.com/health');
errorRate.add(res.status !== 200);
apiLatency.add(res.timings.duration);
}
JMeter – Enterprise Load Testing
Instalação
# Download
wget https://jmeter.apache.org/download_jmeter.cgi
# Run
./bin/jmeter.sh
Plano de Teste (GUI)
Test Plan
├── Thread Group (100 users, 10s ramp-up, loop 10)
│ ├── HTTP Request Defaults
│ │ └── Server: api.exemplo.com
│ │
│ ├── Once Only Controller
│ │ └── Login Request
│ │ └── POST /auth/login
│ │
│ ├── Recording Controller
│ │ └── GET /products
│ │ └── GET /products/{id}
│ │ └── POST /orders
│ │
│ └── Listeners
│ ├── Summary Report
│ ├── View Results Tree
│ ├── Aggregate Report
│ └── Graph Results
JMeter CLI
# Run non-GUI
jmeter -n -t test-plan.jmx -l results.jtl -e -o html-report
# With specific properties
jmeter -n -t api-test.jmx
-Jthreads=100
-Jrampup=10
-Jduration=300
-l results.jtl
Distributed Testing
# jmeter-server (on slave machines)
jmeter-server -Djava.rmi.server.hostname=192.168.1.100
# Run distributed
jmeter -n -t test.jmx
-R192.168.1.100,192.168.1.101,192.168.1.102
-l results.jtl
Gatling – Scala-based Load Testing
Instalação
# Download
wget https://repo1.maven.org/maven2/io/gatling/highcharts/gatling-charts-highcharts-bundle/3.10.5/gatling-charts-highcharts-bundle-3.10.5.zip
unzip gatling-charts-highcharts-bundle-3.10.5.zip
Script Scala
// src/test/scala/LoadSimulation.scala
package simulations
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import io.gatling.jdbc.Predef._
import io.gatling.core.structure.ScenarioBuilder
class ApiLoadSimulation extends Simulation {
val httpProtocol = http
.baseUrl("https://api.exemplo.com")
.acceptHeader("application/json")
.contentTypeHeader("application/json")
.disableCaching
val userFeeder = csv("users.csv").circular.random
val loginScenario: ScenarioBuilder = scenario("Login Flow")
.feed(userFeeder)
.exec(
http("Login")
.post("/auth/login")
.body(StringBody(
"""{"email":"${email}","password":"${password}"}"""
)).asJson
.check(jsonPath("$.token").saveAs("authToken"))
)
.pause(1)
.exec(
http("Get Products")
.get("/products")
.header("Authorization", "Bearer ${authToken}")
.check(status.is(200))
)
.pause(1)
.exec(
http("Create Order")
.post("/orders")
.header("Authorization", "Bearer ${authToken}")
.body(StringBody(
"""{"productId":1,"quantity":2}"""
)).asJson
.check(status.is(201))
)
setUp(
loginScenario
.inject(
rampUsers(100).during(30.seconds),
constantUsersPerSec(50).during(5.minutes),
rampUsers(100).during(30.seconds)
)
.protocols(httpProtocol)
)
.assertions(
global.responseTime.percentile(95).lt(500),
global.successfulRequests.percent.gt(99)
)
.thresholds(
http("Login").responseTime.percentile(99).lt(1000)
)
}
Interpreting Results
Key Metrics
| Métrica | Significado | Target |
|---|---|---|
| P95 Latency | 95{6727d158e4474b0847515bd23a8ee4bebd5f1aac7a18bc968e51d8985dccb442} das requisições | < 500ms |
| P99 Latency | 99{6727d158e4474b0847515bd23a8ee4bebd5f1aac7a18bc968e51d8985dccb442} das requisições | < 1s |
| Throughput | Req/s | > 1000 |
| Error Rate | {6727d158e4474b0847515bd23a8ee4bebd5f1aac7a18bc968e51d8985dccb442} falhas | < 1{6727d158e4474b0847515bd23a8ee4bebd5f1aac7a18bc968e51d8985dccb442} |
| CPU | Utilização | < 80{6727d158e4474b0847515bd23a8ee4bebd5f1aac7a18bc968e51d8985dccb442} |
| Memory | Utilização | < 85{6727d158e4474b0847515bd23a8ee4bebd5f1aac7a18bc968e51d8985dccb442} |
Finding Bottlenecks
// k6 com métricas customizadas
import { Trend } from 'k6/metrics';
const dbLatency = new Trend('db_query_duration');
const externalLatency = new Trend('external_api_duration');
export default function () {
const start = Date.now();
// DB query
const dbRes = http.get(${BASE_URL}/db);
dbLatency.add(Date.now() - start);
// External API
const extStart = Date.now();
const extRes = http.get('https://external-api.com/data');
externalLatency.add(Date.now() - extStart);
}
Conclusão
Testes de carga são essenciais para garantir performance. As chaves são:
- Definir objetivos claros – SLAs e thresholds
- Simular realista – Dados e comportamento reais
- Monitorar infra – CPU, memória, rede
- Analisar resultados – P95, P99, throughput
- Testar regularmente – CI/CD integrado
