docs(testing): document the Rust test-layout conventions
This commit is contained in:
61
docs/testing.md
Normal file
61
docs/testing.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# Testing conventions
|
||||
|
||||
> How Rust tests are laid out across the host-testable crates (`editor`,
|
||||
> `keymap`, `display`). All of these build and run off the xtensa target —
|
||||
> the firmware itself is exercised on hardware, not `cargo test`.
|
||||
>
|
||||
> Project overview: [`../README.md`](../README.md) · doc index:
|
||||
> [`README.md`](README.md).
|
||||
|
||||
## Two shapes, chosen by what the test exercises
|
||||
|
||||
**Unit tests live in the source file.** A `#[cfg(test)] mod tests` block at the
|
||||
bottom of the `.rs` file. It compiles only under `cargo test` (zero cost in the
|
||||
shipped binary — which matters on a 16 MB part), and it gets private access to
|
||||
the module it sits in. This is the default. `keymap/src/lib.rs` is the worked
|
||||
example: 28 tests inline under the decoder they cover.
|
||||
|
||||
**Behavioural tests live in a `src/tests/` submodule.** When a test drives the
|
||||
_whole_ `Editor` through `Key` events and asserts on private state — rather than
|
||||
calling one function in isolation — it isn't really a unit test of any single
|
||||
module. Those go in a `#[cfg(test)] mod tests;` **directory**, one file per
|
||||
theme. The `editor` crate is laid out this way.
|
||||
|
||||
## The `editor` crate's `src/tests/`
|
||||
|
||||
- [`mod.rs`](../editor/src/tests/mod.rs) is the sole `#[cfg(test)] mod tests;`
|
||||
(declared at the bottom of [`lib.rs`](../editor/src/lib.rs)). It holds **every
|
||||
shared helper** (`typed`, `command`, `kinds`, `over`, `palette_editor`, …) and
|
||||
the fixture consts, and it re-exports the crate root with
|
||||
`pub(crate) use crate::*;` so each theme file reaches `Editor`, `Key`,
|
||||
`Effect`, … through a single `use super::*;`.
|
||||
- Each theme file (`editing.rs`, `visual.rs`, `palette.rs`, `search.rs`, …) is
|
||||
just `#[test]` fns plus that one `use super::*;`. No file re-imports the crate
|
||||
root directly.
|
||||
|
||||
Adding a test:
|
||||
|
||||
1. Put it in the theme file matching the surface it exercises. A test that spans
|
||||
surfaces (e.g. edit → format → publish) goes with its _primary_ intent.
|
||||
2. Need a helper used by more than one theme? Add it to `mod.rs`. A helper used
|
||||
by a single theme may stay in that theme file.
|
||||
3. New theme? Add `mod <name>;` to `mod.rs` and a `//!` one-liner to the file.
|
||||
|
||||
## What we deliberately don't use
|
||||
|
||||
- **The top-level `tests/` integration directory.** That dir only sees a
|
||||
crate's public API. The editor's tests read private state (`e.text`,
|
||||
`e.caret`, `e.mode()`), so they must stay in-crate under `#[cfg(test)]`.
|
||||
Reach for `tests/` only to pin a crate's _public_ contract.
|
||||
- **Doctests** for the embedded core. Fine for documenting a public API, but
|
||||
slow and awkward here; the behaviour is covered by the tests above.
|
||||
|
||||
## Running them
|
||||
|
||||
No cargo workspace ties the crates together, so run per crate from its own
|
||||
directory:
|
||||
|
||||
```sh
|
||||
cd editor && cargo test # 224 tests
|
||||
cd keymap && cargo test # 28 tests
|
||||
```
|
||||
Reference in New Issue
Block a user