Something that I feel is often overlooked or left until the end is load/stress testing. Developers don't like dealing with it and usually leave it to the Dev Ops team. But what if we approached this differently? What if developers do 'small' load tests throughout the build phase of the project? What if it is integrated into the CI/CD process?

Local stress testing

Developers should run a stress test on every component that they build. Using a tool like k6 opensource a script can be set up that will (on localhost) batch through all the features that have been built, and ensure that they work under stress, and with IDE's like Visual Studio, you can monitor memory and CPU usage.

This is not a replacement for full load testing completed by Dev Ops, which is normally run on something like jMeter and on dedicated hardware, but it will provide developers with a level of confidence before releasing their code to integration.

Development/Pre-Production environment load testing

A very similar k6 could be set up to run on the development/pre-production environments after a deployment is completed. Again this would increase the confidence when it comes to the point of full load testing, knowing that a simple load test has been completed on each release by the developer.

Regression/Integration testing

k6 can also be used for regression testing, hitting each feature once, but instead of just waiting for a 200 response, this script would also check the body of the response for certain key content/markup. Again this can be run locally during build and as part of the release pipeline to ensure once feature isn't impacting on any others.

CI/CD Load Testing

A final thought, what if after every release a load test is completed? This is documented here https://k6.io/blog/integrating-load-testing-with-azure-pipelines/ for Azure DevOps, and if you integrate this into your release pipeline and not your build pipeline, it will allow you to take advantage for the Auto-redeploy trigger or if Azure App Service deployment slots are being used, the pending deployment can be rejected, and keep the original deployment.

Installing/setting up k6 (Windows)

If you haven't already installed Chocolately, install Chocolatey

From PowerShell install k6 choco install k6

Example scripts


Simple Load Test

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

export const options = {
  stages: [
    { duration: '30s', target: 100 },
    { duration: '1m30s', target: 100 },
    { duration: '20s', target: 0 },
  ],
};

export default function () {
  const res = http.get('https://localhost:8000/');
  check(res, { 'status was 200': (r) => r.status == 200 });
  sleep(1);
}

Batch Load Test

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

export const options = {
  stages: [
    { duration: '5s', target: 50 },
    { duration: '30s', target: 100 },
    { duration: '10s', target: 0 },
  ],
};

const params = {
  timeout: "10s",
};

export default function () {

  const responses = http.batch([
    ['GET', "https://localhost:8000", null, params],
    ['GET', "https://localhost:8000/blog", null, params],    
    ['GET', "https://localhost:8000/photography", null, params],    
  ]);

  check(responses[0], {
    "Home Page 200": res => res.status === 200
  });

  check(responses[1], {
    "Blog Page 200": res => res.status === 200
  });

  check(responses[2], {
    "Photography Page 200": res => res.status === 200
  });

  sleep(1);
}

Regression/Integration Testing

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

export default function () {

  const responses = http.batch([
    ['GET', "https://localhost:8000"],
    ['GET', "https://localhost:8000/blog"],    
    ['GET', "https://localhost:8000/photography"],    
  ]);

  check(responses[0], {
    "Home Page 200": res => res.status === 200,
    "Verify Home Page Text": res => res.body.includes('Technical Architect, Sensei, Photographer, Husband, Dad')
  });

  check(responses[1], {
    "Blog Page 200": res => res.status === 200,
    "Verify Blog Page Text": res => res.body.includes('My thoughts documented... be afraid!')
  });

  check(responses[2], {
    "Photography Page 200": res => res.status === 200,
    "Verify Photography Page Text": res => res.body.includes('Some of my better photos')
  });

  sleep(1);
}

Using k6 Cloud

If your tests are less than 50vu you have it output to the cloud.

k6 login cloud --token <YOUR_K6_CLOUD_API_TOKEN>

k6 run --out cloud script.js

NOTE: different from k6 cloud script.js

Andy Blyth
Andy Blyth

Andy Blyth is a technical architect/senior C# developer, studies martial arts and attempts to write blog posts (when he remembers). He currently works as an Optimizely (Episerver) Technical Architect at the Dept in Manchester, UK.