1

In Artillery, how can I capture the attribute of a random index in a JSON array returned from a GET, so my subsequent POSTs are evenly distributed across the resources?

https://artillery.io/docs/http-reference/#extracting-and-reusing-parts-of-a-response-request-chaining

I'm using serverless artillery to run a load test, which under the hood uses artillery.io .

A lot of my scenarios look like this:

      -
        get:
          url: "/resource"
          capture:
            json: "$[0].id"
            as: "resource_id"
      -
        post:
          url: "/resource/{{ resource_id }}/subresource"
          json:
            body: "Example"

Get a list of resources, and then POST to one of those resources.

As you can see, I am using capture to capture an ID from the JSON response. My problem is that it is always getting the id from the first index of the array.

This will mean in my load test I end up absolutely battering one single resource rather than hitting them evenly which will be a more likely scenario.

I would like to be able to do something like:

capture:
  json: "$[RANDOM].id
  as: "resource_id"

but I have been unable to find anything in the JSONPath definition that would allow me to do so.

Joe Alamo
  • 133
  • 1
  • 7

3 Answers3

4

Define setResourceId function in custom JS code and to tell Artillery to load your custom code, set config.processor to the JS file path:

processor: "./custom-code.js"

   - get:
      url: "/resource"
      capture:
        json: "$"
        as: "resources"
  - function: "setResourceId"
  -  post:
      url: "/resource/{{ resourceId }}/subresource"
      json:
        body: "Example"

custom-code.js file containing the below function

function setResourceId(context, next) {
    const randomIndex = Math.round(Math.random() * context.vars.resources.length);
    context.vars.resourceId = context.vars.resources[randomIndex].id;
}
Rahul Kumar
  • 3,009
  • 2
  • 16
  • 22
1

Using this version:

------------ Version Info ------------
Artillery: 1.7.9
Artillery Pro: not installed (https://artillery.io/pro)
Node.js: v14.6.0
OS: darwin/x64

The answer above didn't work for me.

I got more info from here, and got it working with the following changes:

function setResourceId(context, events, done) {
    const randomIndex = Math.round(Math.random() * (context.vars.resources.length - 1));
    context.vars.resourceId = context.vars.resources[randomIndex].id;
    return done();
}

module.exports = {
  setResourceId: setResourceId
}
jmartori
  • 384
  • 1
  • 5
  • 14
0

This should also work (in one of the newer versions):

  - get:
      url: "/resource"
      capture:
        json: "$[*].id"
        index: "random"
        as: "resource_id"
  - post:
      url: "/resource/{{ resource_id }}/subresource"
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jul 16 '23 at 22:44