| name | add_tests |
| description | Add or update tests for the RARA codebase. Use when implementing non-trivial behavior changes, fixing regressions, tightening TUI rendering, or adding repo-specific test coverage in Rust. Especially relevant for focused unit tests, TUI snapshot tests, agent/runtime regressions, and behavior-driven test updates in this repository. |
Add Tests For RARA
Use this skill when a change in rara needs test coverage or when an existing failing behavior should be captured with a regression test.
Goals
- Prefer focused, behavior-driven tests over broad integration churn.
- Capture the real regression first, then add only enough setup to make the failure explicit.
- Keep tests aligned with the repository's TUI, runtime, and local-first architecture.
Default Testing Strategy
For a non-trivial change, choose the narrowest useful test surface:
-
Pure helper logic:
- Add a unit test next to the helper.
- Prefer direct function assertions.
-
TUI event or state transitions:
- Add tests in
src/tui/runtime/events.rs, src/tui/state.rs, or the nearest focused module.
- Assert on structured state, not incidental strings, unless the visible text is the contract.
-
TUI rendering contracts:
- Use focused render tests in
src/tui/render/*.
- Use snapshot tests when layout, ordering, labels, or visual grouping are the contract.
- Keep snapshots stable and intentionally small.
-
Agent / planning / transcript regressions:
- Add tests that reproduce the exact transcript or state-routing bug with the minimum number of events.
- Prefer asserting the object-level result first, then render output if the bug is presentation-specific.
-
Config / persistence behavior:
- Use
tempdir() and isolate filesystem state.
- Never rely on the current working directory or developer-local paths.
Non-Negotiable Expectations
Bugfixes Need Regression Coverage
Behavior fixes should normally include a focused automated test that reproduces
the fixed behavior or locks the regression boundary.
Manual verification alone is acceptable only when an automated test is not
practical, such as terminal-only behavior that cannot be isolated without
fragile infrastructure. In that case, record the reason in the PR or final
summary.
Prefer The Narrowest Meaningful Surface
Do not default to the whole suite when one focused module proves the change.
Examples:
- TUI state transition:
cargo test tui::state::<test_name> -- --nocapture
- TUI render contract:
- focused
src/tui/render/* test or snapshot
- provider request construction:
- focused
llm::tests::<test_name>
- agent-loop behavior:
- focused
agent::tests::<test_name>
- crate boundary or broad Rust type impact:
- focused test plus
cargo check
Classify CI Failures
When a PR goes red, classify the failure before changing tests:
- implementation bug
- test bug
- workflow/config bug
- unrelated flaky infrastructure
Do not weaken a test to hide an implementation regression. If the test is
wrong, fix the fixture or assertion while preserving the regression intent.
Repository-Specific Guidance
Assertion Style
- Prefer object-level equality assertions when the whole value is the contract.
- Use field-by-field assertions only when each field communicates a distinct
behavior or failure mode.
- Avoid assertions that only check debug text when the same behavior can be
asserted through structured state or typed events.
- Avoid mutating global process environment in tests. Prefer passing
environment-derived inputs through constructors, config structs, or small test
doubles.
TUI Tests
Common places:
src/tui/runtime/events.rs
src/tui/state.rs
src/tui/render/cells.rs
src/tui/render/bottom_pane.rs
Patterns:
- Build a
TuiApp with ConfigManager { path: temp.path().join("config.json") }.
- Feed
TuiEvent values through apply_tui_event(...) when testing runtime/event routing.
- For rendering, build the relevant cell and collect rendered lines with
.display_lines(width).
- If the UI shape is the contract, prefer
insta::assert_snapshot!.
Planning / Transcript Bugs
When fixing plan-mode bugs:
- Assert that the wrong section stays empty if that is the regression.
- Example: planning prose should not populate
exploration_notes.
- Assert the intended destination explicitly.
- Example: notes land in
planning_notes.
- If there is a visible card contract, add a render test for it.
Snapshot Tests
Use snapshots for:
Updated Plan
Awaiting Approval
- model picker overlays
- queued follow-up previews
- other transcript-heavy cards where ordering and grouping matter
Do not use snapshots when a short structural assertion is enough.
When a snapshot changes:
- Review the generated snapshot text before accepting it.
- Confirm that the visible ordering, labels, grouping, and truncation behavior
match the intended user-visible contract.
- Do not accept snapshots only to make CI green.
Runtime / Protocol Tests
For agent-loop, provider, Wire/ACP, or tool-result tests:
- Assert structured request or event payloads where possible instead of
substring-matching serialized JSON.
- Keep fixtures close to the behavior under test and avoid broad provider mocks
when a narrow fake backend is enough.
- If a regression depends on transcript order, assert the ordered typed entries
first, then add rendered text or snapshot coverage only when the UI contract is
also affected.
What Good Tests Look Like Here
A good rara test usually has these properties:
- It names the regression in the test name.
- It uses the smallest realistic fixture.
- It avoids unrelated providers, tools, or file IO.
- It checks the behavior that matters, not every internal detail.
- It remains readable without reverse-engineering a giant setup block.
Common Mistakes To Avoid
- Do not add broad end-to-end coverage for a local helper change.
- Do not depend on machine-local paths, current repo layout, or ambient environment.
- Do not overfit to debug text if the real contract is a state transition.
- Do not update snapshots blindly; verify the new shape is actually intended.
- Do not mix multiple unrelated regressions into one test.
Typical Commands
Run the narrowest relevant tests first.
Examples:
cargo test tui::runtime::events::tests -- --nocapture
cargo test tui::render::cells::tests -- --nocapture
cargo test agent::tests::completes_only_active_plan_step_on_finish -- --nocapture
cargo check
If a change only affects one rendering contract, prefer one focused test target plus cargo check.
For documentation-only or skill-only changes, Rust tests are usually not
needed; run git diff --check and inspect the rendered markdown shape instead.
Heuristics For Choosing Assertions
Prefer this order:
- State assertions
- Structured transcript assertions
- Rendered text assertions
- Snapshot assertions
Use the highest level that still captures the bug precisely.
When To Add A Snapshot
Add or update a snapshot when:
- the user-visible layout is the contract
- multiple sections must stay in a stable order
- labels, grouping, or card boundaries matter
- a previous bug involved the wrong surface being shown
Minimal Workflow
- Reproduce the bug with the smallest focused test.
- Make the test fail for the right reason.
- Implement the fix.
- Re-run the focused test.
- Run
cargo check.
- Only broaden test coverage if the change truly crosses module boundaries.