# Writing a test

A test is a sentence that names it, then a body of ordinary code. In the
body, `assert` fails the test when its condition is false. Here a test
checks an action that says whether a todo is overdue:

`domains/planning/actions/is_overdue.test.jadpo`:

```jadpo
use planning/types { DueAt }

test "a todo due yesterday is overdue" {
    var due: DueAt = "2026-01-14T12:00:00Z"
    var now: DueAt = "2026-01-15T12:00:00Z"
    assert is_overdue(due, now)
}
```

The test sits beside the action's file, so it calls `is_overdue` without
importing it. `test` and `assert` are built in. `DueAt` and `Overdue` are
your app's own types, each brought in by a `use` line from its file, and
here is everything the test uses:

`domains/planning/actions/is_overdue.jadpo`:

```jadpo
use planning/types { DueAt, Overdue }

/// Whether a todo due at `due` is overdue at `now`.
action is_overdue(due: DueAt, now: DueAt) -> Overdue {
    return Overdue(due < now)
}
```

`domains/planning/types/due_at.jadpo`:

```jadpo
/// When a todo is due.
type DueAt = Instant {}
```

`domains/planning/types/overdue.jadpo`:

```jadpo
/// Whether a todo is past its due time.
type Overdue = Bool {}
```

`jadpo test` runs it.

## The sentence names the test

A test's sentence is its name, and it is used once in the whole project.
A second test with the same sentence is `semantic.duplicate_declaration`.
Jadpo's records know a test by the file it sits beside and its sentence
([Stable identity](/docs/stable-identity.md)).

## Each test starts from nothing

Each test gets its own empty database, its own clock and its own fakes.
So tests never depend on each other, and they can run in any order.
