# Test Alice programs

> Write function, RSpec-style, and attribute-based tests, choose matchers, and run focused checks.

Canonical: https://alice-lang.org/documentation/guides/testing/

[Documentation index](https://alice-lang.org/documentation/llms.txt) · [Complete book](https://alice-lang.org/llms-full.txt)

## Test a method

Put tests in `test/**/*.al` or `spec/`. The CLI compiles them with package sources and resolved references; the application's top-level code is not run as test setup.

```alice
# src/pricing.al
def total(price : Int32, count : Int32) : Int32
  price * count
end
```

```alice
# test/pricing_test.al
def test_total
  assert_equal 750, total(250, 3)
  assert total(250, 0) == 0
end
```

```sh
alice test
```

A failing assertion exits with status 1, shows expected and actual values, and gives an Alice source location and rerun command.

## Describe behavior

RSpec-style groups keep related examples together:

```alice
describe "pricing" do
  it "multiplies price and count" do
    expect(total(250, 3)).to eq(750)
  end
  it "handles an empty order" do
    expect(total(250, 0)).to eq(0)
  end
end
```

`context` is a grouping form. Hooks include `before`, `after`, `before_all`, and `after_all`. Use `fit`/`fdescribe` to focus temporarily, and `xit`/`xdescribe`, `pending`, or `skip` for intentionally inactive examples. Remove accidental focus before sharing a suite: focused tests can exclude other examples.

## Matchers

| Family                | Matchers                                                     |
| --------------------- | ------------------------------------------------------------ |
| Equality and identity | `eq`, `be`                                                   |
| Boolean and absence   | `be_nil`, `be_true`, `be_false`, `be_truthy`, `be_falsy`     |
| Comparison            | `be_gt`, `be_ge`, `be_lt`, `be_le`, `be_between`             |
| Approximation         | `be_within(delta).of(expected)`                              |
| Types                 | `be_a`, `be_instance_of`                                     |
| Collections           | `be_empty`, `have_size`, `include`, `contain_exactly`, `all` |
| Text                  | `start_with`, `end_with`, `match`                            |
| Custom behavior       | `satisfy`, `respond_to`                                      |
| Exceptions            | `raise_error`                                                |

Negate with `not_to`. Combine supported expectations with `.and` or `.or`. An exception expectation uses a block, for example `expect { ... }.to raise_error(typeof(Exception), "message")`.

## Attributes and cases

`@[Test]` or `@[Test("description")]` marks a test method. `@[Cases(1, 2, 3)]` supplies a case row; add one attribute per row. Class-based tests receive a fresh instance for each test, with `setup` and `teardown` hooks.

Choose one style per area of a project so the suite remains easy to scan; the runner supports all three forms.

## Focus a run

```sh
alice test test/pricing_test.al
alice test test/pricing_test.al:12
alice test -e pricing
alice test --seed 42 --order random
alice test --fail-fast
alice test --format junit
alice test --profile
```

A line selects an example or the group declared there. `-e` matches text in the full name. Formats are `doc` (default), `progress`, and `junit`. Profiling lists the ten slowest examples. Seeded ordering helps reproduce order-dependent failures.

## A useful development loop

Write a failing example for the intended behavior, confirm the failure, implement the behavior, then refactor while the suite stays green. Test external boundaries separately: an HTTP handler, graphics window, or package publication needs evidence at that boundary.

## Continue reading

- Previous: [Build games and desktop programs](https://alice-lang.org/documentation/guides/games.md)
- Next: [Understand performance](https://alice-lang.org/documentation/guides/performance.md)
