Run multiple load test scripts with K6

K6 (https://docs.k6.io/docs) is a load test framework built with Go and expose scripting via Javascript. By default, we can run one test script at a time. But we have some ways to run multi scripts for easier monitor of test result.

## Use bash
We can link multiple k6 commands like this.

k6 run test1.js ; k6 run test2.js ; …

This is the easiest way to run but the output will be multiple reports according to each command. So this may not be quite useful in case you want to have a centralized report data.

## Use module export
Each k6 test script has an exported default function for the main test. So we can make an index.js at the root folder then import those functions to run.

Example: we have below modules for signIn, signOut, signUp API

// signIn.js
import { config, globalChecks } from ‘../common/index.js’
import http from ‘k6/http’
import { sleep } from ‘k6’
import { Trend, Rate, Counter } from ‘k6/metrics’
export let SignInDuration = new Trend(‘Sign in Duration’)
export let SignInFailRate = new Rate(‘Sign in Fail Rate’)
export let SignInReqs = new Counter(‘Sign in Requests’)
let duration = 500
let rate = 0.1
export let options = {
thresholds: {
‘Sign in Duration’: [`p(95)<${duration}`],
‘Sign in Fail Rate’: [`rate<${rate}`]
}
}
const users = JSON.parse(open(‘../common/users.json’))export default function () {
for (let user of users) {
let res = http.post(__ENV.HOST + config.api.signIn, {
“email”: user.email, “password”: user.password
})
globalChecks(res, duration) || SignInFailRate.add(1)
SignInDuration.add(res.timings.duration)
SignInReqs.add(1)
}
sleep(1)
}
// signUp.jsimport { config, globalChecks } from ‘../common/index.js’
import http from ‘k6/http’
import { sleep } from ‘k6’
import { Trend, Rate, Counter } from ‘k6/metrics’
import faker from ‘cdnjs.com/libraries/Faker’
export let SignUpDuration = new Trend(‘Sign up Duration’)
export let SignUpFailRate = new Rate(‘Sign up Fail Rate’)
export let SignUpReqs = new Counter(‘Sign up Requests’)
let duration = 1000
let rate = 0.1
export let options = {
thresholds: {
‘Sign up Duration’: [`p(95)<${duration}`],
‘Sign up Fail Rate’: [`rate<${rate}`]
}
}
export default function () {
let res = http.post(__ENV.HOST + config.api.signUp, {
“email”: ‘QA_TECH_’ + faker.internet.email(),
“password”: faker.internet.password(),
“language”: “vn”, “gender”: “M”
})
globalChecks(res, duration) || SignUpFailRate.add(1)
SignUpDuration.add(res.timings.duration)
SignUpReqs.add(1)
sleep(1)
}
// signOut.jsimport { config, globalChecks } from ‘../common/index.js’
import * as helper from ‘../common/helper.js’
import http from ‘k6/http’
import { sleep } from ‘k6’
import { Trend, Rate, Counter } from ‘k6/metrics’
export let SignOutDuration = new Trend(‘Sign out Duration’)
export let SignOutFailRate = new Rate(‘Sign out Fail Rate’)
export let SignOutReqs = new Counter(‘Sign out Requests’)
let duration = 500
let rate = 0.1
export let options = {
thresholds: {
‘Sign out Duration’: [`p(95)<${duration}`],
‘Sign out Fail Rate’: [`rate<${rate}`]
}
}
export function setup() {
let userCookies = helper.getCookies()
return { cookies: userCookies }
}
export default function (data) {
let jar = http.cookieJar()
jar.set(__ENV.HOST, ‘leflair.connect.sid’, JSON.parse(data.cookies)[‘leflair.connect.sid’][0].value)
let res = http.get(__ENV.HOST + config.api.signOut)globalChecks(res, duration) || SignOutFailRate.add(1)
SignOutDuration.add(res.timings.duration)
SignOutReqs.add(1)
sleep(1)
}

Then for index.js, we will import the default function as well as options from those modules above.

import * as helper from ‘./common/helper.js’
import { group, sleep } from ‘k6’
import SignInTest from ‘./tests/signIn.js’
import { options as SignInOptions } from ‘./tests/signIn.js’
import SignOutTest from ‘./tests/signOut.js’
import { options as SignOutOptions } from ‘./tests/signOut.js’
import SignUpTest from ‘./tests/signUp.js’
import { options as SignUpOptions } from ‘./tests/signUp.js’
export function setup() {
let userCookies = helper.getCookies()
return {
cookies: userCookies
}
}
let optionsSum = {} // here we use the imported options to create a sum of options to run all tests
Object.entries(SignInOptions.thresholds).forEach(item => optionsSum[item[0]] = item[1])
Object.entries(SignOutOptions.thresholds).forEach(item => optionsSum[item[0]] = item[1])
Object.entries(SignUpOptions.thresholds).forEach(item => optionsSum[item[0]] = item[1])
export let options = {
thresholds: optionsSum
}
export default (data) => {
group(‘Sign in’, () => {
SignInTest()
})
group(‘Sign out’, () => {
SignOutTest(data)
})
group(‘Sign up’, () => {
SignUpTest()
})
sleep(1)
}

Doing the module export way will give us more control on the flow because we can group test as well as create new options or setup functions. It will take more time but the result is nice and useful for report analysis later.

From translator -> Manual QC Engineer -> Automation QA Engineer -> NodeJS Developer -> yearning to learn more

From translator -> Manual QC Engineer -> Automation QA Engineer -> NodeJS Developer -> yearning to learn more