Test data
Project-scoped reusable values you can drop into any test prompt. Mix static and auto-generated fields, embed run-context tokens for per-run uniqueness, and read the resolved snapshot in every run report.
Test data
Test data lets you keep names, emails, IDs, addresses, and other test inputs out of your prompts. Define them once per project and reference them with {{data.<set>.<field>}}.
Sign up as {{data.contact.first_name}} {{data.contact.last_name}}
with email {{data.contact.email}}.The dispatcher resolves each reference before the AI agent sees the prompt, so the agent (and any saved Playwright script generated from a run) only sees real values.
Why use test data
- Less duplication:
{{data.contact.email}}works in every plan that signs up or logs in as the same persona. - Refresh without editing prompts: change a value in one place, every prompt that references it picks up the new value on the next run.
- Auto-generate per run: pick a value type and let it fill a fresh value on every dispatch, so two runs of the same plan create two different records.
- Verifiable: every run report shows a "Test data used" panel with the exact resolved values, frozen for that run.
How to set it up
- From Test plans, click Manage test data in the page header.
- Pick the project the data should belong to (data sets are scoped per project).
- Type a name into Data set name (e.g.
contact) and click + New data set. - The set opens expanded with one empty field. Fill the field name (e.g.
email), pick a mode (Static / Dynamic), and either type a value or click Generate to auto-fill. - Click + Add field to add more (
first_name,last_name,dob,phone, …).
Field name rules: letters (upper- or lower-case), digits, and underscores. Must start with a letter. Max 50 chars. Both snake_case (first_name) and camelCase (firstName) are accepted; references in prompts are case-sensitive.
The modal autosaves on blur; there's no separate "Save" button.
Static vs Dynamic
Each field has a mode that controls when its value is decided.
| Mode | When the value is decided | Use for |
|---|---|---|
| Static | Once, when you set it. Stays the same on every run until you change it. | Stable test personas (the same email logs in every time) |
| Dynamic | On every dispatch. The value type auto-generates a fresh value. | Per-run uniqueness without an extra template (e.g. a fresh email on every run) |
A static field's stored value can itself be a template. Embed {{run.timestampMs}}, {{run.shortId}}, {{pipeline.timestampMs}}, etc. for per-run uniqueness without switching to Dynamic mode:
contact.email = "qa.{{run.timestampMs}}@example.test"The substitution chain resolves the embedded tokens after the fixture lookup, so two runs of the same plan get two different emails (the same way Dynamic mode would), but with full control over the shape.
Value types
Click Generate to auto-fill a value, or click the dropdown next to it to pick a type. Categories include:
- People: first name, last name, full name, job title
- Internet: email, username, URL, IPv4
- Phone
- Location: street address, city, state, ZIP code, country
- Company: company name
- Lorem: word, sentence, paragraph
- Dates: past, future
- Strings: UUID, alphanumeric (with configurable length)
- Numbers: integer (with configurable min / max)
- Boolean
The same category list works for Dynamic mode: pick a type once and every run gets a fresh value of that shape.
Referencing in prompts
Use {{data.<set>.<field>}} anywhere a test plan accepts free text:
- The prompt itself
- Cookie values
- Header values
- Pre-step input values
- Another data set's stored value (templates can chain)
Click Insert value beneath the prompt textarea to pick from a grouped list of every credential, fixture field, run token, and pipeline token in scope.
Date and timezone formatting
Any field that stores a date can be formatted at substitution time:
{{ data.contact.dob | format: 'DD.MM.YYYY' }}
{{ data.contact.dob | format: 'YYYY-MM-DD HH:mm', 'Europe/Bucharest' }}See Template tokens & filters for the full list of format tokens and timezone behavior.
Pipeline-step coordination
When a multi-step pipeline references a Dynamic field, every step in the pipeline sees the same rolled value (the dispatcher rolls once and shares across steps). That's what makes flows like "step 1 creates a contact, step 2 finds the same contact" work.
If you need per-step values, use Static fields: each step's {{run.X}} resolves to that step's own job, so a templated value like qa.{{run.shortId}}@example.test will differ per step.
For values that need to be identical across steps but unique across dispatches, use {{pipeline.X}} instead of {{run.X}} in the template:
contact.email = "qa.{{pipeline.timestampMs}}@example.test"{{pipeline.timestampMs}} is allocated once at dispatch and shared across every step. See Template tokens & filters.
The "Test data used" panel
Every run report includes a Test data used panel showing the resolved values that were actually substituted into that run. The values are frozen with the run, so editing the data set after the fact doesn't change what's shown for past runs.
For multi-step pipelines:
- Test data: each step shows its own snapshot (different pre-steps may live in different projects).
- Pipeline values: every step shows the same
{{pipeline.X}}snapshot (allocated once, shared).
API access
Data sets are managed under the project they belong to:
GET /api/admin/projects/<projectId>/data-fixtures: listPOST /api/admin/projects/<projectId>/data-fixtures: createPUT /api/admin/projects/<projectId>/data-fixtures/<id>: replaceDELETE /api/admin/projects/<projectId>/data-fixtures/<id>: delete
Field shape:
{
"key": "first_name",
"mode": "static",
"value": "Jane",
"generator": "person.firstName"
}For one-off rolls outside a fixture context, POST /api/admin/data-fixtures/roll accepts { generator, options } and returns a single value.