Writing Test Scripts
k6 tests are written in JavaScript. Here's everything you need to write effective load tests.
On this page
The Basics
Every k6 test has two parts: options that configure the test, and a default function that runs once per virtual user iteration.
import http from 'k6/http';
// Options configure the test
export const options = {
vus: 10, // 10 virtual users
duration: '30s', // run for 30 seconds
};
// This runs once per VU iteration
export default function () {
http.get('https://api.example.com/health');
}Checks — Assert Responses
Checks validate that responses meet your expectations. They don't stop the test on failure — they track the pass/fail rate so you can set thresholds.
import http from 'k6/http';
import { check } from 'k6';
export default function () {
const res = http.get('https://api.example.com/users');
check(res, {
'status is 200': (r) => r.status === 200,
'body has users': (r) => JSON.parse(r.body).length > 0,
'response < 300ms': (r) => r.timings.duration < 300,
});
}Thresholds — Pass/Fail Criteria
Thresholds define SLAs. If any threshold is breached, the test fails — perfect for CI/CD integration.
export const options = {
vus: 50,
duration: '5m',
thresholds: {
// 95% of requests must complete under 500ms
http_req_duration: ['p(95)<500'],
// Error rate must be below 1%
http_req_failed: ['rate<0.01'],
// 99% of checks must pass
checks: ['rate>0.99'],
},
};Stages — Ramp VUs Over Time
Stages let you gradually increase and decrease load, simulating realistic traffic patterns like ramp-ups and ramp-downs.
export const options = {
stages: [
{ duration: '1m', target: 20 }, // Warm up to 20 VUs
{ duration: '3m', target: 100 }, // Ramp to 100 VUs
{ duration: '2m', target: 100 }, // Hold at 100 VUs
{ duration: '1m', target: 0 }, // Ramp down to 0
],
};POST Requests with JSON
Send POST, PUT, PATCH, and DELETE requests with custom headers and JSON payloads.
import http from 'k6/http';
import { check } from 'k6';
export default function () {
const payload = JSON.stringify({
name: 'Test User',
email: 'test@example.com',
});
const params = {
headers: { 'Content-Type': 'application/json' },
};
const res = http.post('https://api.example.com/users', payload, params);
check(res, {
'created': (r) => r.status === 201,
});
}Groups — Organize Sequences
Groups let you organize a sequence of requests that represent a user flow, like "browse → add to cart → checkout".
import http from 'k6/http';
import { group, check, sleep } from 'k6';
export default function () {
group('Browse products', () => {
const res = http.get('https://shop.example.com/products');
check(res, { 'listed': (r) => r.status === 200 });
});
group('View product', () => {
const res = http.get('https://shop.example.com/products/1');
check(res, { 'loaded': (r) => r.status === 200 });
});
group('Add to cart', () => {
const res = http.post('https://shop.example.com/cart',
JSON.stringify({ productId: 1, qty: 1 }),
{ headers: { 'Content-Type': 'application/json' } }
);
check(res, { 'added': (r) => r.status === 200 });
});
sleep(1);
}