Carlos Aguni

Highly motivated self-taught IT analyst. Always learning and ready to explore new skills. An eternal apprentice.


K6 Study

16 Sep 2022 »

Install

wget https://github.com/grafana/k6/releases/download/v0.40.0/k6-v0.40.0-linux-amd64.tar.gz
mv k6-v0.40.0-linux-amd64/k6 /usr/local/bin/
k6 version

Learn k6 Series - E1 - Getting Started with k6

git clone https://github.com/QAInsights/Learn-k6-Series.git

Stress Types

Load Testing

https://k6.io/docs/test-types/load-testing/

Load testing is primarily concerned with assessing the current performance of your system interms of concurrent users or requests per second.

export const options = {
  stages: [
    { duration: '5m', target: 100 }, // simulate ramp-up of traffic from 1 to 100 users over 5 minutes.
    { duration: '10m', target: 100 }, // stay at 100 users for 10 minutes
    { duration: '5m', target: 0 }, // ramp-down to 0 users
  ],
  thresholds: {
    'http_req_duration': ['p(99)<1500'], // 99% of requests must complete below 1.5s
    'logged in successfully': ['p(99)<1500'], // 99% of requests must complete below 1.5s
  },
};

export const options = {
  stages: [
    { duration: '5m', target: 60 }, // simulate ramp-up of traffic from 1 to 60 users over 5 minutes.
    { duration: '10m', target: 60 }, // stay at 60 users for 10 minutes
    { duration: '3m', target: 100 }, // ramp-up to 100 users over 3 minutes (peak hour starts)
    { duration: '2m', target: 100 }, // stay at 100 users for short amount of time (peak hour)
    { duration: '3m', target: 60 }, // ramp-down to 60 users over 3 minutes (peak hour ends)
    { duration: '10m', target: 60 }, // continue at 60 for additional 10 minutes
    { duration: '5m', target: 0 }, // ramp-down to 0 users
  ],
  thresholds: {
    http_req_duration: ['p(99)<1500'], // 99% of requests must complete below 1.5s
  },
};

Stress Testing

https://k6.io/docs/test-types/stress-testing

Stress Testing is a type of load testing used to determine the limits of the system. The purpose of this test is to verify the stability and reliability of the system under extreme conditions.

export const options = {
  stages: [
    { duration: '2m', target: 100 }, // below normal load
    { duration: '5m', target: 100 },
    { duration: '2m', target: 200 }, // normal load
    { duration: '5m', target: 200 },
    { duration: '2m', target: 300 }, // around the breaking point
    { duration: '5m', target: 300 },
    { duration: '2m', target: 400 }, // beyond the breaking point
    { duration: '5m', target: 400 },
    { duration: '10m', target: 0 }, // scale down. Recovery stage.
  ],
};

Spike Test

https://k6.io/docs/test-types/stress-testing/#spike-testing

Spike testing is a type of stress testing that immediately overwhelms the system with an extreme surge of load.

export const options = {
  stages: [
    { duration: '10s', target: 100 }, // below normal load
    { duration: '1m', target: 100 },
    { duration: '10s', target: 1400 }, // spike to 1400 users
    { duration: '3m', target: 1400 }, // stay at 1400 for 3 minutes
    { duration: '10s', target: 100 }, // scale down. Recovery stage.
    { duration: '3m', target: 100 },
    { duration: '10s', target: 0 },
  ],
};

Soak Test

export const options = {
  stages: [
    { duration: '2m', target: 400 }, // ramp up to 400 users
    { duration: '3h56m', target: 400 }, // stay at 400 for ~4 hours
    { duration: '2m', target: 0 }, // scale down. (optional)
  ],
};

Learn k6 Series - E7 - Scenarios and Executors

Learn-k6-Series/scenarios-executors/scenarios-executors-demo.js

import { sleep, check } from "k6";
import http from "k6/http";

export const options = {
    scenarios: {
        // per_vu_scenario: {
        //     executor: "per-vu-iterations", //5*5=25 iterations
        //     vus: 5,
        //     iterations: 5,
        //     startTime: '3s'
        // },
        // shared_scenario: {
        //     executor: "shared-iterations", // (5/5)=1 iteration per vu, totally 5 iterations
        //     vus: 5,
        //     iterations: 5,
        //     startTime: '0s'
        // },
        // constant_scenario: {
        //     executor: "constant-vus",
        //     vus: 5,
        //     duration: "5s",
        //     startTime: '0s'
        // },
        // ramping_vus_scenario: {
        //     executor: "ramping-vus",
        //     startTime: '0s',
        //     stages: [{
        //             target: 5,
        //             duration: "15s"
        //         }
        //     ]
        // },
        // constant_arrival_scenario: {
        //     executor: "constant-arrival-rate",
        //     rate: 5,
        //     duration: '20s',
        //     preAllocatedVUs: 5,
        //     maxVUs: 10,
        // },
        // ramping_arrival_scenario: {
        //     executor: 'ramping-arrival-rate',
        //     startRate: 2,
        //     timeUnit: '1s',
        //     preAllocatedVUs: 2,
        //     maxVUs: 20,
        //     stages: [{
        //             target: 15,
        //             duration: '30s'
        //         },
        //     ],
        // },
        externally_controller_scenario: {
            executor: 'externally-controlled',
            vus: 10,
            maxVUs: 30,
            duration: '2m',
        },
    },
};

export default function () {
    const res = http.get("https://onlineboutique.dev");
    sleep(1);
    check(res, {
        'is status 200': r => r.status === 200,
    });
    // console.log(res.body);
}

Learn-k6-Series/httpMethods/httpPost.js

import http from "k6/http";
import { check } from "k6";

export default function() {
    // POST
    let payload = {
        "name": "morpheus",
        "job": "leader"
    }

    let res = http.post("https://reqres.in/api/users", JSON.stringify(payload), {
        headers: {
            "Content-Type": "application/json"
        }});
    console.log("POST Method: The name is " + res.json().name);

    // PUT
    let putPayload = {
            "name": "morpheus frank",
            "job": "zion resident"
    }

    let resPut = http.put("https://reqres.in/api/users/2", JSON.stringify(putPayload), {
        headers: {
            "Content-Type": "application/json"
        }});
    console.log("PUT Method: The new name is " + resPut.json().name);

    // PATCH
    let patchPayload = {
        "name": "morpheus wood",
        "job": "leader"
    }

    let resPatch = http.patch("https://reqres.in/api/users/2", JSON.stringify(patchPayload), {
        headers: {
            "Content-Type": "application/json"
        }});

    console.log("PATCH Method: The patched name is " + resPatch.json().name);

    // DELETE
    let resDelete = http.del("https://reqres.in/api/users/2");
    check(resDelete, {
        'is status 204': (r) => r.status === 204,
    });

    // OPTIONS
    let resOptions = http.options("https://example.org");
    console.log("OPTIONS Method: " + resOptions.headers['Allow']);

    // CUSTOM
    let resCustom = http.request("GET", "https://duckduckgo.com");
    console.log("CUSTOM Method: " + resCustom.status);
}

Analysing results

k6-reporter

https://github.com/benc-uk/k6-reporter

// This will export to HTML as filename "result.html" AND also stdout using the text summary
import { htmlReport } from "https://raw.githubusercontent.com/benc-uk/k6-reporter/main/dist/bundle.js";
import { textSummary } from "https://jslib.k6.io/k6-summary/0.0.1/index.js";

export function handleSummary(data) {
  return {
    "result.html": htmlReport(data),
    stdout: textSummary(data, { indent: " ", enableColors: true }),
  };
}

k6-html-reporter

https://www.npmjs.com/package/k6-html-reporter

GRPC support

https://community.k6.io/t/does-k6-grpc-support-testing-grpc-services/742/4

https://k6.io/blog/performance-testing-grpc-services/