Testing a single api with different payload

Hi Team,

I need to create a test with k6 to assess the performance of an API endpoint using ten different types of payloads. Additionally, I want to establish a threshold for each payload type. How can I accomplish this?

I tried few solution where we can dynamically define the scenario but its not working and giving error as json: cannot unmarshal number into Go struct field Options.scenarios of type string

below is the sample code -

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

// Define an array of 17 payloads
const payloads = [
    { title: "Payload 1", body: "This is payload 1", userId: 1 },
    { title: "Payload 2", body: "This is payload 2", userId: 2 },
    { title: "Payload 3", body: "This is payload 3", userId: 3 },
    { title: "Payload 4", body: "This is payload 4", userId: 4 },
    { title: "Payload 5", body: "This is payload 5", userId: 5 },
    { title: "Payload 6", body: "This is payload 6", userId: 6 },
    { title: "Payload 7", body: "This is payload 7", userId: 7 },
    { title: "Payload 8", body: "This is payload 8", userId: 8 },
    { title: "Payload 9", body: "This is payload 9", userId: 9 },
    { title: "Payload 10", body: "This is payload 10", userId: 10 },
    { title: "Payload 11", body: "This is payload 11", userId: 11 },
    { title: "Payload 12", body: "This is payload 12", userId: 12 },
    { title: "Payload 13", body: "This is payload 13", userId: 13 },
    { title: "Payload 14", body: "This is payload 14", userId: 14 },
    { title: "Payload 15", body: "This is payload 15", userId: 15 },
    { title: "Payload 16", body: "This is payload 16", userId: 16 },
    { title: "Payload 17", body: "This is payload 17", userId: 17 },
];

// Define the options for k6
export let options = {
    scenarios: {},
};

// Create scenarios for each payload with thresholds
payloads.forEach((payload, index) => {
    options.scenarios[`scenario_${index + 1}`] = {
        executor: 'constant-vus',   // Executor type
        vus: 3,                     // Number of virtual users
        duration: '1m',             // Duration for this scenario
        exec: 'testPayload',        // Function to execute
        startTime: `${index}m`,     // Ensure startTime is a string
        env: { PAYLOAD_INDEX: index }, // Pass the payload index as an environment variable
        thresholds: {
            'http_req_duration': [`p(95)<200`], // 95th percentile response time < 200ms
            'http_req_failed': ['rate<0.01'],   // Error rate < 1%
        },
    };
});

// Function to be executed for each scenario
export function testPayload() {
    const payloadIndex = __ENV.PAYLOAD_INDEX; // Get payload index from the environment variable
    const payload = payloads[payloadIndex]; // Retrieve the appropriate payload

    // Make the HTTP POST request
    const res = http.post('https://jsonplaceholder.typicode.com/posts', JSON.stringify(payload), {
        headers: { 'Content-Type': 'application/json' },
    });

    // Check if the response status is 201
    check(res, {
        'status is 201': (r) => r.status === 201,
    });

    sleep(1); // Simulate a wait time between requests
}

And I am running this to save output in timescale db like ./k6 run --out timescaledb=postgresql://localhost:5432/k6 dist/simulations/test.js --tag test_run_id=Test_9

Hi @vish_s02 :wave:

I’ve spotted two main issues that might be getting in your way.

  1. The values of the env dictionary should be string. Just like in Unix-like OSes, the environment in k6 is strings based. In your example, switch the payload index to PAYLOAD_INDEX: index.toString() should address the issue you’ve encountered.
  2. Another issue I’ve noticed is that thresholds are a top-level option, and are not present in the scenario definition. Instead, I believe you’d rather define an empty thresholds object in your initial options, and specifically add the thresholds on a per scenario basis (using tags) in your forEach loop.

Here’s the detail of what I mean:

// Define an array of 17 payloads
const payloads = [
    { title: 'Payload 1', body: 'This is payload 1', userId: 1 },
    { title: 'Payload 2', body: 'This is payload 2', userId: 2 },
]

// Define the options for k6
export let options = {
    thresholds: {},
    scenarios: {},
}

// Create scenarios for each payload with thresholds
payloads.forEach((payload, index) => {
    const scenarioName = `scenario_${index + 1}`

    // Add a scenario for each payload
    options.scenarios[scenarioName] = {
        executor: 'constant-vus', // Executor type
        vus: 1, // Number of virtual users
        duration: '1m', // Duration for this scenario
        exec: 'testPayload', // Function to execute
        startTime: `${index}m`, // Ensure startTime is a string
        env: { PAYLOAD_INDEX: index.toString() }, // Pass the payload index as an environment variable
    }

    // Register thresholds specific to that scenario by targetting it using tags
    Object.assign(options.thresholds, {
        [`http_req_duration{scenario:${scenarioName}}`]: [`p(95)<200`], // 95th percentile response time < 200ms
        [`http_req_failed{scenario:${scenarioName}}`]: ['rate<0.01'], // Error rate < 1%
    })
})

export function testPayload() {
    console.log(`Testing payload`)
}

Hope this helps, let me know if I can be of further assistance :bowing_man: