Skip to main content

Test rules in plain English

Test rules are the assertions that decide whether an API scenario passed. You can let Qodex generate rules from plain English, or write the structured assertion yourself when the check needs to be exact.

How rules differ from scenario steps

A step is what the test does. A rule is what the test expects to see.
LayerPurposeExample
StepPerforms an HTTP actionPOST /users with body { email, name }
RuleAsserts a property of the resultstatus equals 201, body.id exists, body.email equals input email
A single step can carry many rules. A scenario passes only when every step’s rules evaluate true. Rules persist on the step as expectations[], each one a structured assertion:
{
  "expectations": [
    { "kind": "status", "equals": 201 },
    { "kind": "jsonpath", "path": "$.id", "exists": true },
    { "kind": "jsonpath", "path": "$.email", "equals": "${INPUT_EMAIL}" },
    { "kind": "header", "name": "content-type", "contains": "application/json" }
  ]
}
The structured shape is what the runner evaluates. Plain English is one way to author that structure.

Writing rules in plain English

When you ask the agent to author a scenario, it generates rules based on the endpoint’s response schema and common validation patterns. You see them in the Suggested rules panel on the step. Common auto-generated rules:
  • “Status code should be 200.”
  • “Response body should contain user_id.”
  • “Field email should match the input email.”
  • “Error message should appear when email is missing.”
To add your own rule on top, type it in:
The created order should have a total that matches the
sum of the items' prices times their quantities.
Qodex converts that to a structured assertion, saves it on the step, and shows the generated JavaScript so you can verify the conversion.

Writing rules manually

When the English-to-assertion conversion is not sharp enough, write the assertion directly. Open the step, go to the Write tab, and pick a rule kind:
  • Status: equals, in [200, 201, 204], notEquals.
  • JSONPath: exists, equals, notEquals, contains, matches, lengthEquals, lengthGreaterThan.
  • Header: equals, contains, matches, exists on the header name (case-insensitive).
  • Body shape: validate the response body against a JSON Schema or a TypeScript-style shape.
  • Custom JavaScript: a free-form expression that returns truthy for pass, falsy for fail.
Custom JavaScript has access to the response context:
// step.expectations[].kind = "custom"
current_status_code === 201 &&
current_response_body.email === current_request_body.email &&
typeof current_response_body.id === "string" &&
current_response_body.id.length > 0
Available identifiers:
  • current_status_code, current_response_body, current_response_headers.
  • current_request_body, current_request_headers.
  • ${var} interpolation happens before the expression evaluates, so captures and environment variables work.

When to do which

Use plain English when…Use JavaScript when…
The check is a common pattern (status, field existence, equality)The check requires a computation over the response
You want the agent to author and maintain the ruleThe rule depends on multiple fields or an array reduce
You’re prototyping a new scenarioYou’re hand-tuning an established scenario
In practice, let the agent draft and hand-edit the rules where it matters. The agent is fast at shape, such as status and JSONPath checks. Humans are better at business invariants, such as totals matching or audit trails being complete.

What runs at execution time

The runner evaluates expectations[] on every step. A failing expectation:
  • Marks the step fail.
  • Captures the expected and actual values into the test run record.
  • Surfaces in the per-step breakdown in the Test Runs view.
A failing scenario then enters the failure-classification pipeline (real bug vs stale test vs environment issue) on the next run.

On the roadmap

An assertion DSL with operator dropdown lands as part of API Playground phase 2. Database-validation rules (run a SQL query after the API step, compare the row to the expected state) are in active design. The current expectations[] shape will stay as the persistent format; the new DSL is sugar on top.

Scenarios

The structure that carries rules.

Auto-verification on save

Rules run the moment you save.

Request data generation

The data that rules evaluate against.

Findings

What happens when a rule fails on an active scenario.