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

# Writing Test Steps

> Write reliable natural-language test steps: one job per step, plain language, visible labels, and clear pass conditions - no selectors needed.

Good TesterArmy steps read like instructions you would give to a teammate sitting next to you.

Write what a user is trying to do, not how an automation script should do it. The agent observes the app, clicks real UI, recovers from normal UI friction, and verifies the result. Your job is to give it a clear intent and a clean stopping point.

## The short version

* Write steps in plain language.
* Give each step one job.
* Split actions and checks into separate steps.
* Use labels users can see in the UI.
* Avoid selectors, internal component names, and implementation details.
* Tell the agent what must be true before the step can pass.
* Keep a test to one flow - most are 3-10 steps.

## Write Like You Talk

Best:

```txt theme={"theme":"vesper"}
Open the Pricing page from the header.
```

Also good:

```txt theme={"theme":"vesper"}
Create a new project named "Website smoke test".
```

Avoid:

```txt theme={"theme":"vesper"}
Click the button with class .nav-item:nth-child(3), wait 500ms, then assert URL contains /pricing.
```

TesterArmy is not trying to replay selectors. It is trying to act like a user. User-visible labels like **Pricing**, **New Project**, **Save**, **Invite teammate**, and **Run test** are the most useful anchors.

## One Step, One Intent

The agent focuses on the current step and gets only a small preview of what comes next. When a step mixes too many actions, the agent has to decide where the step ends. That creates ambiguity and wastes run time.

Instead of:

```txt theme={"theme":"vesper"}
Log in, create a project, invite a teammate, run a test, and verify the result.
```

Use:

```txt theme={"theme":"vesper"}
Log in with the saved admin account.
Create a new project named "Checkout QA".
Invite qa@example.com to the project.
Run the "Checkout smoke test" test.
Verify the run result is shown as passed.
```

Each step now has a clear beginning, a clear end, and a clear pass condition.

The same rule cuts the other way. Do not expand one intent into mechanical micro-steps - the agent sequences the clicks, typing, and waits inside a step on its own, and every extra step costs run time.

Instead of:

```txt theme={"theme":"vesper"}
Open the new project form.
Enter "Checkout QA" in the name field.
Enter the project URL.
Click the Create button.
Verify the project was created.
```

Use:

```txt theme={"theme":"vesper"}
Create a new project named "Checkout QA".
Verify the new project appears in the project list.
```

## Split Actions From Assertions

Use action steps for doing something. Use assertion steps for checking that something is true.

Good split:

```txt theme={"theme":"vesper"}
Add the Pro plan to the cart.
Verify the cart shows the Pro plan with the correct monthly price.
```

Weaker:

```txt theme={"theme":"vesper"}
Add the Pro plan to the cart and make sure the cart is correct.
```

The split matters because assertion steps are treated as focused verification. The agent can still navigate or scroll if needed, but it should not start changing data, uploading files, or doing unrelated setup during an assertion.

## Use The Right Step Type

TesterArmy supports different step types. Pick the type that matches the job.

| Type | Use it for | Good example |
| - | - | - |
| `act` | User actions | `Open the billing settings page.` |
| `assert` | Verifying state | `Verify the billing page shows the current plan.` |
| `login` | Authentication | `Log in with the saved admin account.` |
| `files` | Using attached files | `Upload the sample invoice PDF.` |
| `screenshot` | Capturing visual evidence | `Capture a screenshot of the completed checkout page.` |

Some step types are web-only: `javascript` and `microphone` steps are only supported on web tests and cannot be added to mobile tests.

`files` steps work on both platforms, with different delivery. On web tests the agent uploads the attached files into the page. On mobile tests the attached photos and videos are preloaded into the device photo library before the run starts, and the agent selects them through your app's own media picker - so mobile projects only accept photo and video uploads (`.png`, `.jpg`, `.jpeg`, `.mp4`, `.mov`).

An `act` step can also use a project file without a separate `files` step: type `@` in the step editor and pick a file from the project's **Files** tab, or write `@` followed by the exact filename, for example `Upload the receipt @receipt-standard-fuel.jpg in the Add Transaction form.` The run looks the file up by name when it starts, so re-uploading a file with the same name keeps the step working. A mention that matches no project file is flagged in the editor, and the step fails with `PROJECT_FILE_MISSING` if it needs that file. On mobile tests, mentioned photos and videos are preloaded into the device photo library like `files` step attachments.

Any step can be disabled instead of deleted: a disabled step stays saved on the test but is skipped by every run, so you can park a step you are not ready to drop and re-enable it later. Set `disabled: true` on the step through the API, or use the disable action in the step editor.

Do not hide login inside a broad action step. If the flow needs authentication, make it a `login` step. Do not ask for screenshots inside normal action or assertion steps; use a dedicated `screenshot` step.

When a flow needs a simple text-based file (for example a CSV import fixture or a JSON config) that is not attached to the test, the agent can generate one on the fly during the run and upload it. Prefer attached project files with a `files` step when the exact file content matters; generated files are best for dynamic flows where any well-formed fixture will do. Generated files are limited to text formats (`csv`, `json`, `md`, `svg`, `txt`, `xml`) and are discarded when the run ends.

Web tests can also download a file from your app and upload that same file later
in the same run. For example, use an `act` step to export a report, another `act`
step to import the downloaded report, and an `assert` step to check the imported
data. The agent keeps repeated exports separate even when their filenames match.
Downloads must finish before reuse, and the downloaded files selected for one upload must total less than 50 MiB. Downloads are available only in that execution attempt; retries
start fresh. Keep using `files` steps for required project attachments.

## Add Context, Not A Script

Good steps include the important business context:

```txt theme={"theme":"vesper"}
Create a new project named "PR preview smoke test".
```

```txt theme={"theme":"vesper"}
Verify the invite list contains qa@example.com with the "Pending" status.
```

They do not need browser-level instructions unless the exact route or label matters:

```txt theme={"theme":"vesper"}
Go to /dashboard/projects and open the "PR preview smoke test" project.
```

Avoid micromanaging timing and mechanics:

```txt theme={"theme":"vesper"}
Click the create button, wait 2 seconds, reload, then inspect the third table row.
```

The agent already waits for page changes, checks fresh page state after important actions, handles transient toasts, and retries normal UI targeting problems. Tell it the goal, not every low-level click.

## Be Specific

Vague checks are harder to evaluate.

Weak:

```txt theme={"theme":"vesper"}
Verify the dashboard looks good.
```

Better:

```txt theme={"theme":"vesper"}
Verify the dashboard shows a Projects card, a Recent Runs card, and no visible error banner.
```

Weak:

```txt theme={"theme":"vesper"}
Check that checkout works.
```

Better:

```txt theme={"theme":"vesper"}
Verify the order confirmation page shows an order number and the customer email.
```

For copy checks, quote exact text only when exact copy matters. If the intent is looser, say so:

```txt theme={"theme":"vesper"}
Verify a success message appears after saving the profile.
```

## Keep Tests Focused

A good test usually covers one user flow. Many useful tests are 3-10 steps, and a test cannot have more than 30.

Length is not just a style preference. Every run shares one time budget across all of its steps, so a long test can spend it before reaching the final steps - and steps that never run produce no verdict. The same applies in the other direction: splitting one intent into many mechanical micro-steps (navigate, type, click as separate steps) spends the budget on step bookkeeping instead of testing.

Split a test when it crosses product areas like signup, onboarding, project creation, invites, billing, or running a QA test. Put the resulting tests in a group and run the group: each test gets its own time budget, a failure points at one flow instead of blocking everything after it, and shared setup like login can move into the group's preparation test instead of being repeated.

## Common Rewrites

| Instead of | Write |
| - | - |
| `Click the blue button in the top right.` | `Click New Project.` |
| `Use selector #email and type the test email.` | `Enter the saved test account email.` |
| `Enter the email. Enter the password. Click Sign in.` (three steps) | `Log in with the saved admin account.` (one login step) |
| `Check the page.` | `Verify the page shows the empty project state.` |
| `Do the full checkout flow.` | `Add the Pro plan to the cart.` |
| `Make sure it worked.` | `Verify the confirmation page shows an order number.` |
| `Wait for AI to finish and check the output.` | `Wait for the generated summary to finish and verify it contains three bullet points.` |

## Review Checklist

Before running a test, scan the steps and ask:

* Could a teammate follow this without seeing the code?
* Does each step have one clear intent?
* Are actions and assertions split?
* Are user-visible labels included where useful?
* Are credentials handled by a login step or saved project credentials?
* Is the expected result specific enough to pass or fail confidently?

If the answer is yes, the agent has a much better chance of producing stable, useful results.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.