Assertion Results and Custom Checks
Read assertion results row by row (expected, actual, passed), and write custom checks whose script log appears right under the result when they fail.
View as MarkdownApplies to: All editions · Web app and Desktop app · Any role that can run tests. Asking the assistant to build a check needs the Project Assistant and an AI provider.
Overview
When a test runs, each of its assertions produces a row in the results: what was expected, what was found, and whether it passed. Shift-Left Studio makes those rows easier to read and act on:
- Every result row is numbered to match the assertion in the editor, and custom checks show their name, so you can tell nine custom checks apart.
- A custom check's Expected and Actual cells say what the check was looking for and what it found, instead of "custom logic to pass / passed".
- A custom check can write log lines that appear under its result row.
- You can copy what any results tab shows as plain text.
- You can state a check in words to the Project Assistant and it builds it for you.
- An assertion's expected value can be a dynamic token, for example a value from a data row.
Key concepts
| Term | What it means |
|---|---|
| Result row | One outcome of one assertion in a run. An assertion can produce more than one row. |
#N badge | The number of the assertion in the editor that produced the row. |
| Custom Assertion | An assertion whose logic is a short JavaScript script you write. |
| Custom Assertion (Request) | The same, but it checks the request that was sent. |
| Script log | Lines a custom check writes with log(...), shown under its result row and in the run log. |
| Dynamic token | A placeholder such as {{row.EXPECTED_STATUS}} in an expected value, filled in when the test runs. |
Before you begin
- Open a test in the Test Workbench (edit, run and see results on one screen).
- To ask the assistant to build a check, the Project Assistant must be available in your workspace and an AI provider configured under Settings → AI Settings.
Step 1 — Find the row for a specific assertion
- Run the test.
- In the results pane, open the Assertions tab.
- Each row carries a
#Nbadge. Hover it to see Assertion N in the editor. That is the card with the same number on the editor's Assertions tab. - A custom check's row reads Custom Assertion — <name>, where the name is the check's own name, for example the
pm.testname from an imported Postman collection. A field check shows its path, for example Field Contains — data.message.
Note: For runs recorded before numbering existed, Studio matches rows to assertions by position only when the assertion type at that position agrees. A row it can't match safely shows no number rather than a wrong one.
Step 2 — Read Expected and Actual for a custom check
For built-in assertions, Expected and Actual are the values compared, for example Expected 201, Actual 200. For a custom check, Studio fills the two cells from what the run actually produced, in this order:
| Source | Example Expected | Example Actual |
|---|---|---|
The script returned expected and actual | status 200 and 3 items | status 200 and 2 items |
The check is a converted Postman script with several pm.test checks | all 8 checks to pass | 6 of 8 passed — failed: … (naming the failed checks) |
| The check has a name, and the script gave a reason | the check's name | the script's reason |
| Nothing more specific is available | custom logic to pass | passed or failed |
When a check passes and nothing more specific is known, Actual repeats Expected, the same way Expected 200 / Actual 200 reads for a status check. Studio never guesses Expected and Actual by reading your script's text, because a confident guess that is sometimes wrong is worse than a plain placeholder.
If the script throws an error, Actual reads error: <message>, so you can tell a broken script apart from a failed check.
Step 3 — Write a custom check that explains itself
- On the editor's Assertions tab, add an assertion and choose Custom Assertion.
- Write the logic. Your script can use these names:
response,request,responseTime,assertion,utilsandlog. The response body isresponse.dataand the status code isresponse.status. - Return either
true/false, or an object withpassedand, optionally,reason,expectedandactual. - Call
log(...)for anything that helps you read a failure later.
Example:
const items = response.data.items || [];
log('items returned:', items.length);
return {
passed: response.status === 200 && items.length === 3,
expected: 'status 200 and 3 items',
actual: `status ${response.status} and ${items.length} items`,
};
Log lines appear in a Script log block under the result row, and in the Logs tab prefixed [SCRIPT]. Studio keeps up to 50 lines per check, each up to 300 characters.
Tip: Returning
expectedandactualis the most useful thing a custom check can do. It turns a wall of identical "passed" rows into rows that say what each one checked.
Step 4 — Copy a results tab
- In the results pane, open the tab you want: Assertions, Response, Request, Variables or Logs.
- Click Copy. The button changes to Copied (or Copy failed if your browser blocked the clipboard).
Studio copies what the tab shows, as readable text, not the raw run record. On the Assertions tab, for example, each row is copied as its number, name, verdict, expected and actual value. This is handy for pasting into a bug report or a chat message.
Step 5 — Ask the assistant to build a check you describe
You can describe a check in plain words and let the Project Assistant build it.
- Open the Project Assistant from the test, or from the floating launcher.
- Say what the check should do, for example "Change assertion 6 so it checks the body is an object" or "Add a check that
data.totalequals the number of items." - The assistant offers a change card showing exactly which assertion it adds or replaces.
- Review the card and accept it. Nothing is changed until you accept.
How the assistant builds it:
- It uses a built-in assertion type when one fits. A check on the body's shape, for example, becomes Response Is Object, with no AI-written code.
- Only when no built-in type fits does it write a custom script, and that script must compile and must call
log(...)so its result can be read. - It refers to assertions by the numbers you see in the editor and in the results.
- If the test's last run was analyzed, the card shows that verdict as a note. When you state the check you want, the assistant builds it rather than refusing because of an earlier verdict.
Note: Like every change the assistant offers, the new assertion goes through the same checks as any other repair. For example, it won't weaken a negative test into one that can never fail.
Step 6 — Use dynamic tokens in expected values
An assertion's expected value can contain a token that is filled in at run time. In the value field, type {{ to pick one.
- In a data-driven test,
{{row.COLUMN}}uses the value from the current data row, for example{{row.EXPECTED_STATUS}}for the status each row should get back. - A value saved by an earlier test's data extraction can be used by name, for example
{{orderId}}.
Tokens are resolved only in the expected value. The field path or header name a check reads from is never treated as a template.
Status-code and other number-type assertions still accept tokens: the value field is a text box so you can type {{row.EXPECTED_STATUS}}.
Generating checks from test-data sheets. When you upload a test-data sheet, columns named EXPECTED_STATUS (or EXPECTED_STATUSCODE, EXPECTED_HTTPSTATUS, EXPECTED_CODE, EXPECTED_RESPONSECODE) and EXPECTED_<path>, such as EXPECTED_data.id, are read as expectations, not inputs. Data-driven tests generated from the sheet check each row's own expected status and fields. That's how one sheet of invalid inputs can mix rows that expect 400 and rows that expect 422.
Understanding the results
| What you see | What it means |
|---|---|
| Green row | The assertion passed. |
| Red row | The assertion failed. Compare Expected and Actual. |
Actual reads error: … | A custom script threw an error. Fix the script, not the API. |
| Needs review on an imported check | A Postman check that hasn't been converted. It reports a failure until converted. See Postman collection import. |
Row with no #N badge | An older run whose row couldn't be matched to an assertion safely. |
Troubleshooting
| Symptom | Why it happens | What to do |
|---|---|---|
| All custom rows read "custom logic to pass / passed" | The scripts return only true/false and the checks have no names. | Return expected and actual from each script. |
A check with .not fails although the value "looks right" | In chai, .not negates every assertion word after it, including after .and. .to.not.be.null.and.to.be.an('object') fails on an object. | Rewrite as separate checks, for example .to.not.be.null and .to.be.an('object'). |
| Copy failed | The browser blocked clipboard access. | Allow clipboard access for the site, or select the text manually. |
| No Script log block appears | The script never called log(...), or it threw before reaching it. | Add log(...) calls early in the script. |
| A token appears literally in Actual | The token name doesn't match a column or variable. | Check the spelling against the data set columns or the extraction's variable name. |
Best practices
- Give each custom check a clear name, and return
expectedandactual. - Prefer built-in assertion types. They explain themselves and run faster than scripts.
- Log the values a check depends on, not the whole response.
- When you report a failing assertion, copy the Assertions tab so the number and values travel with it.
Related articles
Previous
File Uploads and Form Bodies
Product documentation
Next
Fix with AI: Grounded Repair
Product documentation
Related articles
- Generate Endpoint Test Cases · Product documentation
- Test Cases: Open, Edit, and Save · Product documentation
- Test Configuration · Product documentation
- Execution Mode · Product documentation
- Run Tests and Review Results · Product documentation
- Test Generation Settings · Product documentation
Next steps
- Getting started · Install + connect your spec
- Configuration fundamentals · Stabilize runs
- Initial configuration · Users, licensing, projects
- Release notes · Updates and fixes
Still stuck?
Tell us what you’re trying to accomplish and we’ll point you to the right setup—installation, auth, or CI/CD wiring.