---
title: Testing
description: Test application behavior and framework regressions without pinning page markup.
---

Write a test when it protects a behavior that can break independently of an
intentional design or copy change. A component does not need a test merely
because it renders HTML or Markdown.

## Writing unit tests

Keep focused tests for calculations, validation, state transitions, authorization,
and error handling. Exercise different inputs and failure paths. A useful test
should explain what unintended consequence it prevents.

Avoid assertions that repeat the template: headings, footer links, CSS classes,
icon counts, section order, or the presence of a component's own `data-*` marker.
Changing those intentionally should not require editing another copy of the page
inside a test.

Proa's compiler, linter, and renderer tests cover generic template behavior,
escaping, and composition. Application components using those APIs do not need
their own copies of the same tests. Test application-specific handling of
untrusted input when it adds behavior beyond the renderer's guarantees.

## Integration tests

Test boundaries that combine independently changing systems: authentication and
data access, request-scoped loader deduplication, cache invalidation, content
negotiation, HTTP errors, or serving linked browser assets. Prefer a few tests
that exercise complete behavior over a separate render test for every route.

For ordinary library unit tests:

```bash filename="Terminal"
cargo test --lib
```

Application binaries and integration tests that link RSJS islands need the
linked pipeline. Name the relevant target:

```bash filename="Terminal"
proa test -p my_app --test integration
```

A plain `cargo test` integration binary that links RSJS islands fails at link
time because it lacks the compiled JavaScript modules. Library unit tests under
`#[cfg(test)]` are unaffected.

## Writing snapshot tests

Full-page HTML snapshots change whenever the page changes. Do not add them by
default, or build normalization machinery just to keep a changing page snapshot
passing. Use exact-output assertions when the bytes themselves are a stable
contract, such as a serializer or protocol encoder.

## Testing in a browser

Review presentation changes in a browser at the relevant screen sizes. Use
browser automation when it protects a specific workflow, keyboard interaction,
or accessibility behavior that simpler checks cannot exercise. A screenshot or
DOM assertion for every component adds maintenance without necessarily catching
an unintended consequence.

## Catching performance regressions

Measure render and streaming performance with the relevant benchmark on stable
hardware. Keep inputs and workload sizes comparable across runs. A successful
benchmark compilation does not establish that performance stayed the same.

```bash filename="Terminal"
cargo bench -p proa_bench
```

## Organizing tests and CI

Keep unit tests beside the logic they exercise and integration tests under
`tests/`. Add test targets as needed; there is no required suite per component or
page. Group related integration cases when separate linked test binaries would
repeat expensive builds.

Run formatting and Proa's source checks alongside the relevant behavior tests:

```bash filename="Terminal"
cargo fmt --all -- --check
proa check
```

See [CI / GitHub Actions](/docs/guides/ci) for the pinned CLI setup and linked
application build commands.
