DEV Community

Cover image for πŸš€ Performance Testing: Types and Implementation with k6
Juan Castillo
Juan Castillo

Posted on

πŸš€ Performance Testing: Types and Implementation with k6

🎯 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
Enter fullscreen mode Exit fullscreen mode

πŸ› οΈ 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
Enter fullscreen mode Exit fullscreen mode

πŸ› οΈ Grafana configuration

## grafana-dashboard.yaml
apiVersion: 1
providers:
  - name: 'default'       
    org_id: 1             
    folder: ''            
    type: 'file'          
    options:
      path: /var/lib/grafana/dashboards
Enter fullscreen mode Exit fullscreen mode
## grafana-datasource.yaml
apiVersion: 1

datasources:
  - name: k6influxdb
    type: influxdb
    access: proxy
    database: k6
    url: http://influxdb:8086
    isDefault: true
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
  • 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);
}
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

πŸƒ 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
Enter fullscreen mode Exit fullscreen mode

Linux / Mac

docker-compose run k6 run /scripts/load.js
Enter fullscreen mode Exit fullscreen mode

🎬 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)