Skip to content

Data-driven testing ​

When ten tests differ only in their input, write one request and a table of inputs. The runner sends the request once per row. Adding a case becomes adding a line, and the table itself is a readable record of what was tested.

When to use it ​

  • The same endpoint with many valid inputs: products, currencies, languages.
  • Boundary values around a limit: 0, 1, 10, 11.
  • A list of invalid inputs that should all be refused.
  • The same journey for several users or roles.

Not for cases that need different steps. Those are separate requests.

The data file ​

A CSV file has a header row of variable names, then one row per case:

csv
productId,quantity,expectedStatus
1,1,201
2,3,201
3,10,201
1,11,422
2,50,422

A JSON file is an array of objects with the same names:

json
[
  { "productId": 1, "quantity": 1,  "expectedStatus": 201 },
  { "productId": 1, "quantity": 11, "expectedStatus": 422 }
]

Each column becomes a variable for that pass. In the request, use it like any other variable.

Build one ​

Using POST /orders and shop-orders.csv from the Shop API sample.

  1. Write the request body with variables where the data goes:

    json
    {
      "productId": {{productId}},
      "quantity": {{quantity}}
    }
  2. Open the runner for the request, folder or collection.

  3. Select Load data file and choose the CSV. The runner shows a preview of the rows.

  4. Select Run. There is one pass per row.

A value from the file wins over a collection or environment variable of the same name for that pass. See Data-driven runs for the exact rules on files, quoting and types.

Expected results per row ​

A no-code test has one fixed expected value: Status equals 201 cannot become 422 for row four. Two ways to handle rows that expect different results:

Split the file. One file of inputs that should succeed, run against a request that tests for 201. A second file of inputs that should fail, run against a copy that tests for 422. No code, and each file states its purpose.

Put the expectation in the file and read it in a post-response script:

js
const expected = Number(pm.iterationData.get('expectedStatus'));
pm.test('status is ' + expected, function () {
  pm.response.to.have.status(expected);
});

pm.iterationData.get('name') returns the current row's value. See Scripts.

Choosing the rows ​

A good table is small and deliberate. For each input:

PickFor a quantity of 1 to 10
A typical value3
The lowest valid value1
The highest valid value10
Just below the range0
Just above the range11
Far outside50, -1
The wrong kind of thingabc, empty

Seven rows cover what seven hundred random ones would not. Add a note column saying why each row exists; the runner ignores columns the request does not use.

csv
quantity,expectedStatus,note
1,201,lowest valid
10,201,highest valid
0,422,below range
11,422,just above range

Generated data ​

When the exact value does not matter, only that it is fresh, use a dynamic variable instead of a file: {{$randomEmail}}, {{$guid}}, {{$randomInt}}. Each send gets a new value, which avoids "that email is already registered" on the second run.

Use a file when you need to know the input in order to judge the output. Use dynamic variables when you only need uniqueness.

Data-driven workflows ​

Run a whole folder with a data file, and each pass runs the full journey with that row's values: sign in as this user, order this product, check the result. Captured values chain within a pass and do not leak into the next row.

From the command line ​

The same file works in CI:

bash
apiworkbench-cli run shop-api.apiworkbench.json --folder Orders -d shop-orders.csv

See Automating in CI.

Common mistakes ​

  • A header name that does not match the variable. Quantity and quantity are different.
  • Quotes inside JSON bodies. A text value needs its quotes in the body: "name": "{{name}}". A number does not.
  • Hundreds of rows. If a row fails, can you say what it was testing? If not, it should not be there.
  • Secrets in data files. A CSV of real credentials is a leak waiting for a commit.

Next steps ​