> ## Documentation Index
> Fetch the complete documentation index at: https://docs.testorim.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Writing tests in plain English

> What to say so a test passes for the right reason.

## The shape of a good instruction

Say **what to do** and **what should be true afterwards**.

```text theme={null}
Sign in with demo@example.com / secret123, add the first product to the cart,
and check the cart badge shows 1.
```

That sentence names a starting point, an action sequence, and an observable
outcome. All three matter.

## Rules that earn their keep

<AccordionGroup>
  <Accordion title="Name things you have actually seen" icon="eye">
    Testorim does not know your site's wording before it opens it, and it will
    not invent copy. Write *"check the confirmation message appears"*, not
    *"check it says 'Thanks! Your order #12345 is confirmed.'"*, unless you
    have read that exact string on the page.

    A test that asserts invented copy fails against a perfectly healthy site.
  </Accordion>

  <Accordion title="One workflow per test" icon="route">
    A plan holds up to 40 steps. That is enough for checkout with cart
    arithmetic and a confirmation, but not for sign-up *and* checkout *and*
    account deletion. Split them, and you also get three independent signals
    instead of one.
  </Accordion>

  <Accordion title="State the outcome explicitly" icon="target">
    "Check the search works" gives nothing to verify. "Search for 'backpack'
    and check at least one result mentions Backpack" does.

    If you ask for a check and no step performs it, the run says so rather
    than passing quietly.
  </Accordion>

  <Accordion title="Be specific when the page is repetitive" icon="list">
    On a listing page, *"click the product"* is ambiguous and *"click the
    first product"* is not. For a row-scoped control, name the row: *"click
    Delete in the Blue Top row"*.
  </Accordion>

  <Accordion title="Use a selector when words fail" icon="code">
    If an element genuinely has no accessible name, label, placeholder or test
    id, write its selector as the target: `#order-total`, `.toast`,
    `[data-testid="cart"]`. A target starting with `#`, `.` or `[` is treated
    as CSS and matched exactly.
  </Accordion>

  <Accordion title="Give slow things room" icon="timer">
    For a scrape, import or batch job, raise the time limit and describe the
    finished state loosely (*"wait until the page shows it is complete"*)
    rather than guessing the exact completion phrase.
  </Accordion>
</AccordionGroup>

## Worked comparisons

| Instead of                                   | Write                                                                                                                                                                        |
| -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| "Test the login page"                        | "Sign in with [demo@example.com](mailto:demo@example.com) / secret123 and check the dashboard heading appears"                                                               |
| "Check checkout works"                       | "Add the first product to the cart, go to checkout, fill the form with test data, submit, and check the order confirmation appears"                                          |
| "Make sure validation is right"              | "Submit the signup form with an empty email and check an error appears under the email field" *(mark it **Should fail** if you mean the submission itself must be rejected)* |
| "Check the page says 'Welcome back, Sarah!'" | "Check a welcome message appears in the header"                                                                                                                              |
| "Click the button"                           | "Click the Add to cart button"                                                                                                                                               |

## Negative tests

Mark a test **Should fail** when the app is supposed to refuse. The run passes
when the action is correctly rejected.

```text theme={null}
Try to check out with an expired card and verify the payment is refused.
```

Do not use it for a test you expect to break. It is about the *app's* intended
behaviour, not your prediction.

## Credentials and secrets

Put real credentials in the instruction only for throwaway test accounts. For
anything else:

* Let Testorim ask: leave the credentials out and it shows a masked form.
* Use [variables](/projects/variables-and-secrets) for values that change per run.
* Use [environment cookies and headers](/projects/environments) for real
  secrets: they are encrypted at rest and never reach a model.

Values typed into password, secret, token, PIN, OTP, CVV and SSN fields are
redacted before the run is stored, before the report is written, and before
anything is shared.


## Related topics

- [What is Testorim](/index.md)
- [CLI](/developers/cli.md)
- [Core capabilities](/introduction/core-capabilities.md)
- [Create your first test](/getting-started/first-test.md)
- [Projects](/projects/projects.md)
