Skip to content

Environment Matrix Mechanism

env_matrix runs one scenario multiple times, once per combination of a set of environment variables (a Cartesian product). It lets you run the same workflow against different data without copying .sinq files or directories.

Definition and Cartesian Product

The env_matrix property in a .scenario file takes an array of objects. Each object represents an axis in the matrix. The keys in these objects serve as labels, and their values are the environment variable overrides/additions applied to that specific branch of the execution. The objects must have all their top-level keys correspond to objects. Empty objects ({}) are safely ignored and dropped by the parser.

config.scenario:

{
  "env_matrix": [
    {
      "admin": { "role": "admin", "auth_token": "sys-jwt-999" },
      "guest": { "role": "guest", "auth_token": "guest-jwt-111" }
    },
    {
      "card": { "method": "card", "expected_status": 200 },
      "crypto": { "method": "crypto", "expected_status": 202 }
    }
  ]
}

During the Treewalker aggregation phase, sinq gathers all of these arrays into a single flat array of objects. Then the runner dispatches the resulting scenario combined with every possible combination of environments from these objects (creating a Cartesian product by picking exactly one key-value pair from each axis object). These combinations are then deep merged with the static env for this particular run. The example above yields 4 distinct data sets that are sent to the worker pool:

  1. admin_card: role="admin", auth_token="sys-jwt-999", method="card", expected_status=200
  2. admin_crypto: role="admin", auth_token="sys-jwt-999", method="crypto", expected_status=202
  3. guest_card: role="guest", auth_token="guest-jwt-111", method="card", expected_status=200
  4. guest_crypto: role="guest", auth_token="guest-jwt-111", method="crypto", expected_status=202

Each generated scenario appends its labels to the base scenario name, e.g. checkout_admin_card.

Note

Because the combination parsing relies on Go map iteration, the generation and execution sequence of the matrix combinations is inherently non-deterministic.

Usage in Requests

The generated matrix values are injected directly into the scenario's environment. They can be accessed via standard interpolation (${env.variable}) in the raw HTTP text or inside Lua scripts via the env global table.

01_checkout.sinq:

POST ${env.BASE_URL}/checkout
Authorization: Bearer ${env.auth_token}
Content-Type: application/json

{
    "role": "${env.role}",
    "payment_method": "${env.method}"
}

$ASSERT{
    sinq.assert.code(env.expected_status, "Matrix status code mismatch for " .. env.role .. " using " .. env.method)
}

Inheritance and Deep Merging

Matrix environments follow the normal Treewalker inheritance rules:

  1. Base Environment Overrides: Values generated by a matrix combination take precedence over the base env aggregated for the scenario. The matrix values are deep-merged on top of the base environment.
  2. Parent-Child Matrix Multiplication: If a parent directory defines an env_matrix, and a child directory also defines its own env_matrix, the child inherits the parent's axes. This results in the matrix expanding exponentially as the dimensions are multiplied together.

Warning

Be cautious when nesting matrices deeply within the directory tree, as it can unintentionally generate a massive number of concurrent workers and exhaust network or system resources.