π― Introduction
Performance testing is crucial to ensure your app can handle traffic like a champ! Whether you're preparing for Black Friday or just want to avoid angry users, different types of tests help identify bottlenecks and improve system stability. In this article, weβll explore four key performance tests and show you how to implement them using k6 (an open source tool and cloud service that makes load testing easy for developers and QA engineers).
π³ Setting Up k6 with Docker
Want to automate and visualize your test results? Set up k6 with Docker, InfluxDB, and Grafana! π
src
|_scripts/
|_docker-compose.yml
|_grafana-dashboard.yaml
|_grafana-datasource.yaml
π οΈ Docker Compose Configuration
networks:
k6:
grafana:
services:
influxdb:
image: influxdb:1.8
# entrypoint: /bin/sh
# user: root
networks:
- k6
- grafana
ports:
- "8086:8086"
environment:
- INFLUXDB_DB=k6
grafana:
image: grafana/grafana:8.5.21
# entrypoint: /bin/sh
# user: root
networks:
- grafana
ports:
- "3000:3000"
environment:
- GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
- GF_AUTH_ANONYMOUS_ENABLED=true
- GF_AUTH_BASIC_ENABLED=false
- GF_SERVER_SERVE_FROM_SUB_PATH=true
volumes:
- ./dashboards:/var/lib/grafana/dashboards
- ./grafana-dashboard.yaml:/etc/grafana/provisioning/dashboards/dashboard.yaml
- ./grafana-datasource.yaml:/etc/grafana/provisioning/datasources/datasource.yaml
k6:
image: grafana/k6:latest
# entrypoint: /bin/sh
# user: root
networks:
- k6
ports:
- "6565:6565"
environment:
- K6_OUT=influxdb=http://influxdb:8086/k6
volumes:
- ./scripts:/scripts
π οΈ Grafana configuration
## grafana-dashboard.yaml
apiVersion: 1
providers:
- name: 'default'
org_id: 1
folder: ''
type: 'file'
options:
path: /var/lib/grafana/dashboards
## grafana-datasource.yaml
apiVersion: 1
datasources:
- name: k6influxdb
type: influxdb
access: proxy
database: k6
url: http://influxdb:8086
isDefault: true
With this setup, you can store k6 test results in InfluxDB and analyze them in Grafana like a pro! π
Run InfluxDb and Grafana
- Run the command
docker-compose up influxdb grafana -d
- After that you can access to the Grafana dashboard in localhost:3000 also you can change the port in the docker-compose file.
π€ What Does Performance Mean for an API?
Before diving into testing, let's define what "performance" means for your API. Ask yourself:
What will the API be used for?
How much traffic per instance is acceptable?
What are the maximum acceptable response times?
Answering these questions helps set benchmarks for successful testing. β
ποΈ Types of Performance Tests
1οΈβ£ Load Testing
Goal: Measure system behavior under normal and maximum expected loads.
Use Case: Find out how many users your system can handle before things start breaking. π¨
Example Implementation:
import http from 'k6/http';
import { check, sleep } from "k6";
const isNumeric = (value) => /^\d+$/.test(value);
const default_vus = 5;
const target_vus_env = `${__ENV.TARGET_VUS}`;
const target_vus = isNumeric(target_vus_env) ? Number(target_vus_env) : default_vus;
export let options = {
stages: [
{ duration: "5s", target: target_vus },
{ duration: "10s", target: target_vus },
{ duration: "5s", target: 0 }
],
thresholds: {
http_req_failed: ['rate<0.01'], // 99% of request should be success
http_req_duration: ['p(95)<500'], // 95% of response time < 500ms
},
};
export default function () {
const response = http.get("https://swapi.dev/api/people/30/");
check(response, { "status is 200": (r) => r.status === 200 });
sleep(.300);
}
2οΈβ£ Stress Testing
Goal: Find out when your system will break under extreme conditions. ποΈπ₯
Use Case: Push your API to the limit and see when it starts crying for help. π
Example Implementation:
import http from 'k6/http';
import { sleep, check } from 'k6';
export const options = {
stages: [
{ duration: '1m', target: 100 },
{ duration: '2m', target: 100 },
{ duration: '1m', target: 200 },
{ duration: '2m', target: 200 },
{ duration: '1m', target: 500 },
{ duration: '2m', target: 500 },
{ duration: '1m', target: 0 },
],
};
export default function () {
const res = http.get("https://swapi.dev/api/people/30/");
check(res, { 'status was 200': (r) => r.status === 200 });
sleep(1);
}
3οΈβ£ Soak Testing
Goal: Check long-term system stability under constant load. π°οΈ
Use Case: Find memory leaks or slow performance over time. π’
Example Implementation:
import http from 'k6/http';
import { sleep, check } from 'k6';
export const options = {
stages: [
{ duration: '1m', target: 200 },
{ duration: '4h', target: 200 },
{ duration: '1m', target: 0 },
],
};
export default function () {
const res = http.get("https://swapi.dev/api/people/30/");
check(res, { 'status was 200': (r) => r.status === 200 });
sleep(1);
}
4οΈβ£ Spike Testing
Goal: Test how your system handles sudden bursts of traffic. π
Use Case: Simulate a flash sale and see if your API survives. π·οΈπ₯
Example Implementation:
import http from 'k6/http';
import { sleep, check } from 'k6';
export const options = {
stages: [
{ duration: '30s', target: 100 },
{ duration: '1m', target: 2000 },
{ duration: '10s', target: 2000 },
{ duration: '1m', target: 100 },
{ duration: '30s', target: 0 },
],
};
export default function () {
const res = http.get("https://swapi.dev/api/people/30/");
check(res, { 'status was 200': (r) => r.status === 200 });
sleep(1);
}
π Run test
Now we can run any of the tests, for this example each Javascript file must be inside the "scripts" folder in the root of the project
Windows
docker-compose run k6 run //scripts//load.js
Linux / Mac
docker-compose run k6 run /scripts/load.js
π¬ Conclusion
Performance testing is your secret weapon for keeping users happy and preventing downtime. By running Load, Stress, Soak, and Spike tests with k6 and leveraging Docker for monitoring, youβll ensure your system stays fast and reliable. π Happy Coding!
Top comments (0)