Introduction
Performance testing ensures your system can handle expected load. This guide covers load testing with k6 and Artillery - modern, scriptable tools for testing API and web performance.
Testing Types
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Performance Testing Types โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ Load Testing โ
โ โข Normal expected load โ
โ โข Peak load scenarios โ
โ โข Duration: 10-30 minutes โ
โ โ
โ Stress Testing โ
โ โข Beyond normal capacity โ
โ โข Find breaking point โ
โ โข Test recovery โ
โ โ
โ Spike Testing โ
โ โข Sudden traffic increase โ
โ โข How fast can you scale? โ
โ โ
โ Soak Testing โ
โ โข Extended period (hours) โ
โ โข Find memory leaks โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
k6
Setup
# Install k6
brew install k6
# or
npm install -D k6
# Run test
k6 run test.js
Basic Script
// test.js
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
stages: [
{ duration: '30s', target: 10 }, // Ramp up
{ duration: '1m', target: 10 }, // Stay at 10 users
{ duration: '30s', target: 0 }, // Ramp down
],
};
export default function () {
const res = http.get('https://api.example.com/users');
check(res, {
'status is 200': (r) => r.status === 200,
'response time < 500ms': (r) => r.timings.duration < 500,
});
sleep(1);
}
Advanced Options
export const options = {
// Virtual users
vus: 10,
duration: '2m',
// Thresholds (fail test if exceeded)
thresholds: {
http_req_duration: ['p(95)<500'], // 95% under 500ms
http_req_failed: ['rate<0.01'], // Error rate < 1%
},
// Setup and teardown
setup: () => { /* run once */ },
teardown: () => {/* run once */},
};
export default function () {
// Group related requests
group('User flow', () => {
const login = http.post('/login', JSON.stringify({email: '[email protected]'}));
check(login, { 'login success': (r) => r.status === 200 });
const user = http.get('/profile', {
headers: { 'Authorization': `Bearer ${login.json().token}` },
});
check(user, { 'get profile': (r) => r.status === 200 });
});
}
Artillery
Setup
npm install -D artillery
YAML Configuration
# test-config.yml
config:
target: "https://api.example.com"
phases:
- duration: 60
arrivalRate: 5
name: "Warm up"
- duration: 120
arrivalRate: 20
name: "Sustained load"
- duration: 30
arrivalRate: 50
name: "Stress test"
plugins:
expect: {}
processor: "./handlers.js"
scenarios:
- name: "Get users"
flow:
- get:
url: "/api/users"
capture:
- json: "$.users[0].id"
as: "userId"
expect:
- statusCode: 200
- contentType: json
- name: "Create user"
flow:
- post:
url: "/api/users"
json:
name: "Test User"
email: "[email protected]"
expect:
- statusCode: 201
Running
# Run test
npx artillery run test-config.yml
# Quick test
npx artillery quick --duration 10 --rate 10 https://api.example.com
Metrics to Track
# Key performance metrics
metrics:
response_time:
- "p50: Median response time"
- "p95: 95th percentile"
- "p99: 99th percentile"
throughput:
- "requests per second"
- "transactions per second"
errors:
- "error rate"
- "timeout rate"
resources:
- "CPU usage"
- "Memory usage"
- "Network I/O"
CI Integration
# GitHub Actions
- name: Load Test
run: |
k6 run \
--out json=k6-results.json \
--summary-export=k6-summary.json \
test.js
env:
K6_CLOUD_TOKEN: ${{ secrets.K6_CLOUD_TOKEN }}
Key Takeaways
- k6 - Scriptable, JavaScript, great for developers
- Artillery - YAML-based, simple configuration
- Test early - Catch performance issues in CI
- Set thresholds - Fail builds on regressions
Comments