Building a Load Testing Framework using K6.io — Uploading Files (Part 3)

Kushal Bhalaik
Towards Dev
Published in
3 min readOct 27, 2023

--

In Part-02 of this article series, we saw how to add support for managing multiple configs and environments. In this article, we will dive into uploading files which is a key component for very peculiar software applications that involves measuring performance when a bunch of data is uploaded and waiting for processing. Let’s begin!!

The open() function:

Before we begin and add code to the framework we are building, it’s important to understand the open() function, what it does, and when to use it. You can use this function for data files such as JSON files or other document files such as .pdf for image files.

//Loading a local JSON file using open()
const data = JSON.parse(open('./data.json'));
export default function () {
console.log(data.my_key);
}

To load a binary file we need to pass in “b” as the second argument.

// Loading a binary file using open()
const file = open('./Invoice-1.pdf', 'b');
export default function () {
...
}

Loading the files into memory from the file system is done using the open() function. In order for your framework to be able to access files during the runtime you need to load all those test data files in the init context.

Note: open() should always be invoked in init context and we need to provide a list of file beforehand during init context (k6 limitation)

You can also go through the following example to see how it would work.

Data Uploads

https://k6.io/docs/examples/data-uploads/?ref=kushalbhalaik.xyz

Extending the Framework:

Step 1: Extending the init.js

In Part-02, we created a file /code/common/init.js, which is responsible for the init context in this framework. Now in order to include loading files from the memory during context initialization we will add this to the constructor.

const configPath = "../../config";
const filePath = "../../files";

class InitFactory {
constructor() {
...

// list of file from JSON file
this.fileList = this.activeConfig.CONTENT.fileList
// array holding opened document details
this.availableFiles = [];
this.fileList.forEach(fileName => this.availableFiles.push({
name: fileName,
file: open(filePath + "/" + fileName, "b")
}))
}

in order to get the fileList there are two options:

1)using a separate .json file (example below)

this.fileList = JSON.parse(open(filePath + "/" +"list.json"))

2) get it from the config files (used in the above example)

additionally, we can create a getter function in the InitiFactory class to fetch a random file

// returns a random document
getARandomFile() {
const fileIndex = Math.floor(Math.random() * this.fileList.length)
const fileName = this.fileList[fileIndex]
const searchedFile = this.availableFiles.filter((doc) => doc.name === fileName)
return searchedFile[0]
}

and the config files can be extended to include fileList array as follows:

once this is done we are almost done, all we need to do now is use the available files in our script code.

Note: make sure files passed in fileList should be present in the files/ directory otherwise you might get an error message like below

Step 2: Script for file upload

In order to retrieve a file during script execution we can use the getARandomFile() function created inside init.js. Now we can add the following code to testSuite() aka default function inside the script

...
//file upload
let newFile = init.getARandomFile();

// requestBody for fileUpload
const requestBody = {
file: http.file(newFile.file, newFile.name),
};
const fileUploadResponse = http.post(`${baseUrl}/upload`,
requestBody
)
//log the name from api response
console.log(fileUploadResponse);

Note:
I’m using a non-existent endpoint called /upload to showcase the usage of Multipart request (uploading a file) which will throw a 404 error during the execution of the above code.

--

--