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

# Agentic or deterministic

> Choose agentic or deterministic actions and assertions for your end-to-end tests.

Agentic testing lets you describe a user's intention and the expected
result in natural language. The agent can choose the actions to perform
and judge whether the screen meets your expectations. Your test focuses
on the outcome, with no selectors to maintain as the UI changes.

Deterministic testing specifies the actions and checks in code. Both
approaches can test user outcomes, and e2e lets you mix them in one test.

## When to use agentic tests?

Use agentic tests when UI changes keep forcing you to update selectors
in your tests. They also suit flows that take many interactions but are
easy to describe in plain English, such as filling out and submitting a form.

`agent.act` lets you describe a user intention, such as applying a
discount code. The agent figures out which controls to use and what to do.
`agent.assert` checks whether the screen shows the result you describe,
such as a discount applied to the total.

For example, inside a test with the `app` and `agent` fixtures:

```ts
await app.open('/checkout');
await agent.act('apply the discount code SUMMER');
await agent.assert('the checkout shows code SUMMER applied with a 10% discount');
```

You don't need to name the discount field, the button that applies it,
or the element that shows the result.

Tests tied to CSS classes or test IDs need edits when those identifiers
change. Move a button or redesign a form, and the agent can still carry
out the user's intention using what's on screen.

Agentic tests enable monitoring with real data on staging or production
without seeding deterministic data, because agents adapt to your app.
Use a test account there: the model sees what's on screen. See
[Security](https://e2e.com/docs/security).

For a complex journey, write a sequence of goals in plain English. Keep
each goal to one outcome and check it before continuing. See
[Goals](https://e2e.com/docs/core-concepts#goals) for how to split a journey into steps.

## When to use agentic assertions?

Agentic assertions are useful when several wordings or layouts would
satisfy the same requirement. For example, a validation message can
explain what's wrong without matching one exact sentence:

```ts
await agent.assert('the error message explains that an email address is required');
```

For a visual check, add `vision: true` so the model also sees a screenshot:

```ts
await agent.assert('the chart trends upward', { vision: true });
```

`agent.assert` checks the current screen and fails if the statement is
false or the evidence is insufficient. Use `agent.waitFor` when the UI
still needs time to reach the expected state. See
[Assertions](https://e2e.com/docs/core-concepts#assertions) for both methods.

## When to use deterministic tests?

Use locators for short, stable flows where you already know which controls
to use. You specify each field and button in code, as in this discount test:

```ts
await app.open('/checkout');
await screen.getByLabel('Discount code').fill('SUMMER');
await screen.getByRole('button', 'Apply').tap();
await expect(screen.getByRole('status')).toHaveText('10% off');
```

These actions and checks make no model calls. Prefer roles and labels so
the test refers to controls the user recognizes. Deterministic tests don't
have to depend on CSS classes or test IDs.

Use deterministic assertions when you can express the expected result
as an exact value, count, or state. They check it without model judgment.
If a validation message must use specific wording, check that text with
`expect`.

## Combine agentic with deterministic tests

Choose actions and assertions independently. You can let the agent find
its way through a changing UI, then check an exact value with `expect`:

```ts
await agent.act('apply the discount code SUMMER');
await expect(screen.getByRole('status')).toHaveText('10% off');
```

You can also use locators to fill and submit a form, then use
`agent.assert` to check whether its validation message explains the problem.

Adaptation follows the goal you write. A vague instruction can allow a
result you didn't intend. If a specific path matters, name it in the goal
or use locators for those actions. An `expect` after `agent.act` catches
a goal that passed the wrong way.

Model-driven actions and assertions add latency and cost, and can make
mistakes. The [replay cache](https://e2e.com/docs/cache) can repeat recorded `agent.act`
actions without model calls. Assertions run again on every test run.
When a recording no longer matches, the agent can adapt to the changed
UI unless strict cache mode is enabled. See
[Self-healing tests](https://e2e.com/docs/self-healing) for how this works.

## Next

<CardGroup cols={2}>
  <Card title="Core concepts" icon="lightbulb" href="/core-concepts">
    Write goals, assertions, and locator steps.
  </Card>
  <Card title="Self-healing tests" icon="bandage" href="/self-healing">
    See how an agent recovers when a recorded flow changes.
  </Card>
</CardGroup>
