# Read a failure

> Read the failure card, look through a run with inspect, and find every file a run left.

Source: https://rehearsal.dev/retest/essentials/read-a-failure

A failed test prints one card. It holds what you need to act, and says each fact once.

## The failure card

```text
  ✗ tests/tasks.retest.ts › saves a task  5.6s

    Check failed     toHaveText
    Locator          getByTestId('saved-task')
    Page             http://127.0.0.1:4173/
    - Expected       "Release checklist"
    + Received       "Saving…"
    Compared         whole text, ends trimmed, each run of spaces or line breaks read as one space
    Waited           5s for toHaveText, looked 14 times, limit 5s

    tests/tasks.retest.ts:7:3
      5 │   await page.getByTestId('task-title').fill('Release checklist')
      6 │   await page.getByTestId('save-task').click()
    › 7 │   await expect(page.getByTestId('saved-task')).toHaveText('Release checklist')
      8 │ })

    Screenshot       .retest/runs/<time>/artifacts/…/screenshot-failure-1.png
    Rerun            npx retest run tests/tasks.retest.ts:3
    Inspect          npx retest inspect .retest/runs/<time> --test "tests/tasks.retest.ts > saves a task"
```

| Line | What it says |
| --- | --- |
| The first line | The test, its variant when it has one, and how long it ran |
| **Check failed** | The kind of failure, then the matcher or the action |
| **Locator** | The locator, as the test wrote it |
| **Page** | The page's title and address when it failed |
| **Expected** and **Received** | The two values, or a diff when they run over several lines |
| **Compared** | How the text was compared |
| **Waited** | How long the check looked, how many times, and its limit |
| The code | The lines around the call that failed |
| **Screenshot** | A screenshot of each app's page, taken after the test |
| **Rerun** | The command that runs this test again, on the same target |
| **Inspect** | The command that shows every step the test took |

## Kinds of failure

| Kind | Card says | Means |
| --- | --- | --- |
| `check_failed` | Check failed | A check did not pass in its time. |
| `not_found` | Not found | The locator matched nothing in its time. |
| `ambiguous` | Ambiguous | The locator matched more than one element, so nothing was done. |
| `not_actionable` | Not actionable | The element was there, but covered, hidden, disabled or on another page. |
| `timeout` | Timed out | The test or the command ran out of time. |
| `session_lost` | Browser lost | The browser was lost before the input went. |
| `outcome_unknown` | Outcome unknown | The input may have reached the page, and Retest cannot tell. |
| `setup_failed` | Setup failed | A browser, an app server, a secret or a sign-in could not be made ready. |
| `unsupported` | Unsupported | The test used something Retest does not do yet. |
| `usage` | Usage error | The test or the command line asked for something Retest refuses. |
| `no_assertions` | No assertions | The test made no check. |
| `not_awaited` | Not awaited | An action or a check was not awaited. |

A test ends passed, failed, error, not run, inconclusive or skipped. Failed means a check failed. Error means something kept Retest from checking. Inconclusive means an [AI check](https://rehearsal.dev/retest/ai-checks.md) could not decide.

## Inspect a run

`retest inspect` reads a run folder and never runs anything. With `--test`, it shows every step of one test in time order.

```sh
npx retest inspect .retest/runs/<time>
npx retest inspect .retest/runs/<time> --test "tests/tasks.retest.ts > saves a task"
npx retest inspect .retest/runs/<time> --json
```

```text
     20 ms  navigated to "Tasks" at http://127.0.0.1:4173/, by goto
    209 ms  click getByRole('button', { name: 'Save' })  45 ms
    263 ms  ✓ toHaveText getByTestId('saved-task')  54 ms
              looked 2 times, passed on o2: 1 match, text "Release checklist"
    272 ms  ✓ toMatch  1 ms, 1 look, reported by the test file
```

- Each navigation shows the page's title and what opened it: a `goto`, an action, or the page itself.
- Under a check, it shows the looks the check took and the one its verdict rested on.
- A value check passes on the test file's own word, and the timeline says so.
- With `--target app=name`, it shows the test on one target. `--json` prints everything as one document.

> [!NOTE]
> A run that stopped before writing its result is rebuilt from its events and marked incomplete. It never reads as a pass.

## The run folder

Without `--output`, a run goes to `.retest/runs/<time>`. Paths inside it are relative, so you can move or zip the folder.

```text
<run>/events.jsonl                one event per line, written as it happens
<run>/result.json                 written once, at the end; missing means the run did not finish
<run>/logs/<file>.log             a test file's output
<run>/logs/browser-<target>.log   each browser's own output
<run>/logs/app-<name>.log         the output of a server Retest started
<run>/artifacts/                  screenshots, recordings and frames, by attempt and app
<run>/diagnostics/                each page's console and network records
<run>/report.html                 the HTML report, when asked for
.retest/last-run.json             the tests the last run did not pass
```

[Reports and evidence](https://rehearsal.dev/retest/essentials/reports-and-evidence.md) explains the report, the events and what each file holds.
