Skip to content

Commit 2aa3991

Browse files
KSXGitHubclaude
andauthored
docs(dev/guide): document the external-file unit-test module convention (#397)
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 697ad36 commit 2aa3991

5 files changed

Lines changed: 28 additions & 0 deletions

File tree

.github/copilot-instructions.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Read and follow the CONTRIBUTING.md file in this repository for all code style c
1616
- For error types, only derive `Display` and `Error` from `derive_more` when each is actually needed. Not all displayable types are errors.
1717
- Minimize `unwrap()` in non-test code. Use proper error handling instead.
1818
- Prefer `#[cfg_attr(..., ignore = "reason")]` over `#[cfg(...)]` when skipping tests. Use `#[cfg]` on tests only when the code cannot compile under the condition, such as when it references types or functions that do not exist on other platforms.
19+
- A unit-test module may sit inline as `mod tests { ... }` when it is short. Once it grows long enough to noticeably extend the parent, move it to an external file and declare the module with `#[cfg(test)] mod tests;` at the end of the parent. The external file lives at `src/foo/tests.rs` for a parent `src/foo.rs`, and at `src/foo/bar/tests.rs` for a parent `src/foo/bar.rs`. Use this layout even when the parent has no other submodules.
1920
- Install the toolchain before running tests: `rustup toolchain install "$(< rust-toolchain)" && rustup component add --toolchain "$(< rust-toolchain)" rustfmt clippy`.
2021
- When you change CLI arguments, help text, or anything that affects command-line output, run `./generate-completions.sh` to regenerate the shell completion files, the help text files, `USAGE.md`, and the man page. **Do not attempt to regenerate these files manually.** Always use the script.
2122
- Validate changes with `FMT=true LINT=true BUILD=true TEST=true DOC=true ./test.sh`. When a test fails with a hint about `TEST_SKIP`, follow the hint and rerun with the suggested variable. When a sync test fails, read its error message and run the exact command it reports.

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Read and follow the CONTRIBUTING.md file in this repository for all code style c
1616
- For error types, only derive `Display` and `Error` from `derive_more` when each is actually needed. Not all displayable types are errors.
1717
- Minimize `unwrap()` in non-test code. Use proper error handling instead.
1818
- Prefer `#[cfg_attr(..., ignore = "reason")]` over `#[cfg(...)]` when skipping tests. Use `#[cfg]` on tests only when the code cannot compile under the condition, such as when it references types or functions that do not exist on other platforms.
19+
- A unit-test module may sit inline as `mod tests { ... }` when it is short. Once it grows long enough to noticeably extend the parent, move it to an external file and declare the module with `#[cfg(test)] mod tests;` at the end of the parent. The external file lives at `src/foo/tests.rs` for a parent `src/foo.rs`, and at `src/foo/bar/tests.rs` for a parent `src/foo/bar.rs`. Use this layout even when the parent has no other submodules.
1920
- Install the toolchain before running tests: `rustup toolchain install "$(< rust-toolchain)" && rustup component add --toolchain "$(< rust-toolchain)" rustfmt clippy`.
2021
- When you change CLI arguments, help text, or anything that affects command-line output, run `./generate-completions.sh` to regenerate the shell completion files, the help text files, `USAGE.md`, and the man page. **Do not attempt to regenerate these files manually.** Always use the script.
2122
- Validate changes with `FMT=true LINT=true BUILD=true TEST=true DOC=true ./test.sh`. When a test fails with a hint about `TEST_SKIP`, follow the hint and rerun with the suggested variable. When a sync test fails, read its error message and run the exact command it reports.

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Read and follow the CONTRIBUTING.md file in this repository for all code style c
1616
- For error types, only derive `Display` and `Error` from `derive_more` when each is actually needed. Not all displayable types are errors.
1717
- Minimize `unwrap()` in non-test code. Use proper error handling instead.
1818
- Prefer `#[cfg_attr(..., ignore = "reason")]` over `#[cfg(...)]` when skipping tests. Use `#[cfg]` on tests only when the code cannot compile under the condition, such as when it references types or functions that do not exist on other platforms.
19+
- A unit-test module may sit inline as `mod tests { ... }` when it is short. Once it grows long enough to noticeably extend the parent, move it to an external file and declare the module with `#[cfg(test)] mod tests;` at the end of the parent. The external file lives at `src/foo/tests.rs` for a parent `src/foo.rs`, and at `src/foo/bar/tests.rs` for a parent `src/foo/bar.rs`. Use this layout even when the parent has no other submodules.
1920
- Install the toolchain before running tests: `rustup toolchain install "$(< rust-toolchain)" && rustup component add --toolchain "$(< rust-toolchain)" rustfmt clippy`.
2021
- When you change CLI arguments, help text, or anything that affects command-line output, run `./generate-completions.sh` to regenerate the shell completion files, the help text files, `USAGE.md`, and the man page. **Do not attempt to regenerate these files manually.** Always use the script.
2122
- Validate changes with `FMT=true LINT=true BUILD=true TEST=true DOC=true ./test.sh`. When a test fails with a hint about `TEST_SKIP`, follow the hint and rerun with the suggested variable. When a sync test fails, read its error message and run the exact command it reports.

CONTRIBUTING.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,30 @@ ExitCode::from(match self {
346346
})
347347
```
348348

349+
## Unit Tests
350+
351+
A unit-test module may either sit inline as `mod tests { ... }` in its parent or live in a dedicated external `tests` submodule. Use the inline form for short test modules. Once the block becomes long enough to obscure the surrounding module, move the tests into an external file.
352+
353+
### When the inline form is acceptable
354+
355+
The inline form `mod tests { ... }` is acceptable on its own. Reserve it for modules whose entire test suite fits in a small number of lines, so the block does not noticeably extend the parent. Use the number of lines as the deciding factor.
356+
357+
### Where the external file sits
358+
359+
When the tests live externally, the parent declares them at the end of the file with the standard declaration:
360+
361+
```rust
362+
#[cfg(test)]
363+
mod tests;
364+
```
365+
366+
The external file itself sits in a directory named after the parent, using the same path regardless of whether the parent has any other submodules. Concretely:
367+
368+
- For `src/foo.rs`, the tests file is `src/foo/tests.rs`.
369+
- For `src/foo/bar.rs`, the tests file is `src/foo/bar/tests.rs`.
370+
371+
Do not flatten the tests into a sibling file such as `src/foo_tests.rs`, and do not skip the intermediate directory when the parent currently has no other submodules. This mirrors the flat file pattern (`module.rs` rather than `module/mod.rs`) described under [Module Organization](#module-organization).
372+
349373
## Setup
350374

351375
Install the required Rust toolchain and components before running any checks:

template/ai-instructions/shared.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Read and follow the CONTRIBUTING.md file in this repository for all code style c
1616
- For error types, only derive `Display` and `Error` from `derive_more` when each is actually needed. Not all displayable types are errors.
1717
- Minimize `unwrap()` in non-test code. Use proper error handling instead.
1818
- Prefer `#[cfg_attr(..., ignore = "reason")]` over `#[cfg(...)]` when skipping tests. Use `#[cfg]` on tests only when the code cannot compile under the condition, such as when it references types or functions that do not exist on other platforms.
19+
- A unit-test module may sit inline as `mod tests { ... }` when it is short. Once it grows long enough to noticeably extend the parent, move it to an external file and declare the module with `#[cfg(test)] mod tests;` at the end of the parent. The external file lives at `src/foo/tests.rs` for a parent `src/foo.rs`, and at `src/foo/bar/tests.rs` for a parent `src/foo/bar.rs`. Use this layout even when the parent has no other submodules.
1920
- Install the toolchain before running tests: `rustup toolchain install "$(< rust-toolchain)" && rustup component add --toolchain "$(< rust-toolchain)" rustfmt clippy`.
2021
- When you change CLI arguments, help text, or anything that affects command-line output, run `./generate-completions.sh` to regenerate the shell completion files, the help text files, `USAGE.md`, and the man page. **Do not attempt to regenerate these files manually.** Always use the script.
2122
- Validate changes with `FMT=true LINT=true BUILD=true TEST=true DOC=true ./test.sh`. When a test fails with a hint about `TEST_SKIP`, follow the hint and rerun with the suggested variable. When a sync test fails, read its error message and run the exact command it reports.

0 commit comments

Comments
 (0)