Contents ▼

Code Blocks

If you need more control than you can get from the graphical scripting interface, throw in a freestyle code block! These code blocks are similar to the JavaScript Validation Rules and Capturing Rules, except that they can exist independently of any other step, and they don’t have to be run on a response.

Code blocks give you more power than ordinary graphical scripting by allowing looping, conditionals, etc.

To add a code block to your script, just click Add Code Block.

Scope

Code blocks are individually scoped to the v-user that is executing them. If you declare a variable for one v-user, it will exist only for that v-user, and not for others who are running the same load test.

Globals

Beyond all the usual JavaScript language constructs, Loadster code blocks expose a few important objects specific to Loadster that you can use in your scripts.

User

The user object is global within the context of a single v-user. It represents the v-user currently executing the code block. This user object exposes the following methods:

// All the standard HTTP methods
user.get(url, args);
user.post(url, body, args);
user.put(url, body, args);
user.patch(url, body, args);
user.delete(url, args);
user.options(url, args);
user.trace(url, args);

// Get and set user variables
user.getVariable(name);
user.getVariable(name, 3); // get column 3, if the variable is multi-column dataset
user.setVariable(name, value);

// Wait a specified number of milliseconds (these are synonymous)
user.wait(milliseconds);
user.sleep(milliseconds);

It’s important to note that these methods are all synchronous, so there is no need to do a promise chain or callbacks or anything like that. The actual processing is done behind the scenes by Loadster’s v-user anyway, so synchronous programming is not necessarily the dangerous practice it might seem to be if you come from a background in ordinary JavaScript development.

Console

Code blocks also expose a simple console for logging:

console.log(message);

Messages written to the console show up in the script logs and aid you in debugging the script.

JSON

If you’re testing APIs, you’ll often need to parse JSON to look at specific properties. You can use the ordinary JSON.parse for this.

var simple = JSON.parse("{a: 1}"); // parse an arbitrary JSON string
var body = JSON.parse(response.bodyAsString); // parse the response body in a validator

XML

Since XML parsing isn’t a standard language feature of JavaScript, Loadster includes the open source xmldoc parser. There is additional documentation for this parser available on GitHub, but here’s a quick example:

var xml = XML.parse(response.bodyAsString);
var users = xml.childrenNamed("user");

Examples

Nothing like learning by example! Here are a few examples of things you can do in code blocks.

HTTP Requests

The special user object (representing the current v-user) has methods for all of the common HTTP methods (GET, POST, etc).

// GET
user.get("https://slothereum.cc");

// GET with additional page resources
user.get("https://slothereum.cc", {
    resources: [
        "/style.css",
        "/favicon.ico"
    ]
});

// POST with a JSON body and custom header
user.post(
    "https://api.slothereum.cc/transactions",
    {
        source: "08c2d5",
        destination: "9a6bce",
        amount: 1.05
    },
    {
        headers: {
            "Content-Type": "application/json"
        }
    }
);

// POST with a form body
user.post(
    "https://admin.slothereum.cc/login",
    "username=sloth&password=chunk",
    {
        headers: {
            "Content-Type": "application/x-www-form-urlencoded"
        }
    }
);

// DELETE
user.delete("https://api.slothereum.cc/receipts/1133423");

Request Headers

You can pass custom request headers with each request, either as an object with key-value pairs, or in an array.

// Pass request headers in an object
user.get("https://slothereum.cc/api/profile", {
    headers: {
        "Accept": "application/json"
    }
);

// Pass request headers in an array
user.get("https://slothereum.cc/api/profile", {
    headers: [
        { name: "Accept", value: "application/json" }
    ]
);

Response Validation

Validators (similar to the Validation Rules that you can use with ordinary HTTP steps) call a JavaScript function to examine the response and return true if it’s valid, or false if it’s not.

Validator functions can be normal JavaScript functions or the newer ES2016+ arrow functions.

You can specify multiple validator functions for a single response.

// A POST with a JSON body and validator function that requires an HTTP 201 status
user.post(
    "https://api.slothereum.cc/transactions", 
    {
        source: "08c2d5",
        destination: "9a6bce",
        amount: 1.05
    }, 
    {
        headers: [
            { name: "Content-Type", value: "application/json" }
        ],
        validators: [
            // regular function validator syntax
            function (response) {
                return response.status == 201;
            },
            // arrow function validator syntax works too!
            response => response.status === 201
        ]
    }
);

Response Capturing

Often, the server will send you some data that you need to save and use later in your script.

In code blocks, you can capture these from the response and store them using a validator function. Note that we use the validators for capturing too; there is no separate property for Capturing Rules as there is with ordinary HTTP steps.

Simply call user.setVariable(name, value) anywhere in your code block to set a user variable. These special user variables are available for the v-user’s entire iteration of the Loadster script, unlike ordinary JavaScript variables which are scoped to the individual code block and may not be available to subsequent steps.

// Create a random numeric string between 0-999999
let random = String(Math.round(1000000 * Math.random()))

// POST to register an account with the random username and capture a user_id
user.post(
    "https://admin.slothereum.cc/register",
    {
        username: "sloth_" + random,
        password: "chunk"
    },
    {
        headers: {
            "Accept": "application/json",
            "Content-Type": "application/json"
        },
        validators: [
            response => {
                var body = JSON.parse(response.bodyAsString);

                if (body.profile.user_id) {
                    user.setVariable("user_id", name); // save the user_id for later

                    return true; // valid response! treat as a success
                } else {
                    return false; // invalid response! treat as a failure
                }
            }
        ]
    }
);

Loops & Conditionals

Looping and conditionals can be done with all the usual JavaScript language constructs. This trivial example shows looping with a for loop, the % modulus function, an if statement, and setting and getting special user variables with variable interpolation of ${random}.

console.log("We're in a nonsensical code step.");
console.log("It exists only to demonstrates random numbers, user vars, and conditionals.");

// Set a user variable to a random integer from 0 to 19
user.setVariable("random", Math.floor(Math.random() * 20));

// Loop and make 20 requests, with a random value and random wait times
for (var i = 0; i < 20; i++) {
    if (i % 2 == 0) {
        user.get("https://example.com/evens/${random}");
    } else {
        user.get("https://example.com/odds/${random}");
    }
    
    user.wait(Math.random() * 2000);
}

Limitations

Keep in mind that code blocks aren’t actually running in your browser, so be careful not to confuse them with on-page JavaScript (jQuery, React, etc). The scripts are executed on the load engine by your Loadster virtual users and have access to certain special objects like user, response, console, etc.

Getting Help

If you get stuck, we’re happy to help! Please contact support@loadster.app and tell us all about it. We are always super interested in how you’re using code blocks in Loadster.