Fixture-driven harnesses (Fret)
This skill is for turning large, repetitive Rust test matrices into data-driven fixtures with a thin harness.
It reduces merge conflicts, makes review easier, and keeps scenario intent visible.
When to use fixtures (and when not to)
Good fits:
- conformance tables (many cases, same runner, different inputs/expected)
- geometry/layout placement matrices
- policy matrices using the same arbitration rules
- any test file that keeps growing because new behavior means “add another case”
Keep in Rust instead:
- highly procedural interactions where the logic is the test
- cases requiring closures/async hooks or bespoke host wiring
- tests where compile-time types are the primary safety net
Inputs to collect (ask the user)
- What is the repeated dimension (inputs, expected outputs, environment knobs)?
- Does each case share the same runner/harness, or do you need multiple harnesses?
- What must be stable IDs (case id, scenario id, golden id)?
- Do you need deterministic geometry (avoid floats) or will tolerances be required?
- How should failures be reported (case-id-addressable, diff-friendly output)?
Defaults if unclear:
- Start with a single fixture file with
schema_version + stable cases[].id, and a thin harness that prints failing ids.
Smallest starting point (one command)
cargo nextest run -p fret-ui-shadcn
Quick start
- Pick a single “god test” to extract first.
- Read the fixture reference note before defining the schema.
- Mirror the old test with a thin harness before deleting anything.
- Keep failures case-id-addressable and review-friendly.
Workflow
0) Read the reference note first
Use this note to keep the main skill lean:
.agents/skills/fret-fixture-driven-harnesses/references/fixture-schema-and-harness.md
1) Decide whether fixtures are the right tool
Use fixtures when the runner stays the same and only the data changes.
If the behavior is a procedural multi-frame interaction, prefer fret-diag-workflow instead.
2) Extract one matrix incrementally
- copy the existing Rust matrix into a fixture file
- keep the old test temporarily
- mirror the assertions in a thin harness
3) Keep the harness thin and deterministic
The harness should mostly be:
- parse fixture,
- iterate cases,
- call
run_case,
- assert with stable case ids in failure output.
4) Gate first, delete second
Only remove the old “god test” after:
- the fixture harness is green,
- failures are clearly case-id-addressable,
- reviewers can inspect the fixture diff without decoding harness internals.
Definition of done (what to leave behind)
- Minimum deliverables (3-pack): Repro (fixture suite), Gate (nextest), Evidence (case-id failures). See
fret-skills-playbook.
- Fixture suite has
schema_version and stable case id keys.
- Harness is thin (parse →
run_case → asserts) and does not depend on cwd.
- Failing output is case-id-addressable.
- Old matrix tests are removed only after the fixture harness is green and reviewed.
Evidence anchors
- Fixture-driven test examples:
ecosystem/fret-ui-shadcn/tests/web_vs_fret_layout.rs
ecosystem/fret-ui-shadcn/tests/data_grid_layout.rs
ecosystem/fret-ui-shadcn/tests/resizable_panel_group_layout.rs
- Goldens (overview + conventions):
goldens/README.md
- Layering boundaries:
tools/check_layering.py
- Diagnostics scripts for procedural cases:
tools/diag-scripts/ui-gallery-intro-idle-screenshot.json
- This skill’s reference:
.agents/skills/fret-fixture-driven-harnesses/references/fixture-schema-and-harness.md
Examples
- Example: replace a growing matrix test with fixtures
- User says: "This test file keeps growing—every change adds another case."
- Actions: extract cases into
fixtures/*.json, keep a thin harness, and make failures case-id-addressable.
- Result: smaller diffs, fewer conflicts, clearer intent.
Common pitfalls
- Using fixtures for procedural state machines.
- Making fixtures too clever (unstable IDs, floats everywhere, hard-to-diff shape).
- Letting the harness grow beyond parsing +
run_case + asserts.
Troubleshooting
- Symptom: fixtures depend on
cwd and fail in CI.
- Fix: load with
include_str! + env!("CARGO_MANIFEST_DIR").
- Symptom: fixtures are hard to review.
- Fix: keep stable
ids, prefer integers/enums, and split large suites by subsystem.
Related skills
fret-diag-workflow
fret-shadcn-source-alignment
fret-boundary-checks
1---2name: fret-fixture-driven-harnesses3description: This skill should be used when the user asks to "convert a large test matrix", "reduce god test files", "add fixture-driven conformance", or "make repetitive scenarios reviewable". Provides a workflow for JSON fixtures + thin Rust runners (shadcn/Radix conformance, overlay placement matrices) to reduce merge conflicts and keep behavior reviewable.4---56# Fixture-driven harnesses (Fret)78This skill is for turning **large, repetitive Rust test matrices** into **data-driven fixtures** with a thin harness.9It reduces merge conflicts, makes review easier, and keeps scenario intent visible.1011## When to use fixtures (and when not to)1213Good fits:1415- conformance tables (many cases, same runner, different inputs/expected)16- geometry/layout placement matrices17- policy matrices using the same arbitration rules18- any test file that keeps growing because new behavior means “add another case”1920Keep in Rust instead:2122- highly procedural interactions where the logic is the test23- cases requiring closures/async hooks or bespoke host wiring24- tests where compile-time types are the primary safety net2526## Inputs to collect (ask the user)2728- What is the repeated dimension (inputs, expected outputs, environment knobs)?29- Does each case share the same runner/harness, or do you need multiple harnesses?30- What must be stable IDs (case id, scenario id, golden id)?31- Do you need deterministic geometry (avoid floats) or will tolerances be required?32- How should failures be reported (case-id-addressable, diff-friendly output)?3334Defaults if unclear:3536- Start with a single fixture file with `schema_version` + stable `cases[].id`, and a thin harness that prints failing ids.3738## Smallest starting point (one command)3940- `cargo nextest run -p fret-ui-shadcn`4142## Quick start43441. Pick a single “god test” to extract first.452. Read the fixture reference note before defining the schema.463. Mirror the old test with a thin harness before deleting anything.474. Keep failures case-id-addressable and review-friendly.4849## Workflow5051### 0) Read the reference note first5253Use this note to keep the main skill lean:5455- `.agents/skills/fret-fixture-driven-harnesses/references/fixture-schema-and-harness.md`5657### 1) Decide whether fixtures are the right tool5859Use fixtures when the runner stays the same and only the data changes.6061If the behavior is a procedural multi-frame interaction, prefer `fret-diag-workflow` instead.6263### 2) Extract one matrix incrementally6465- copy the existing Rust matrix into a fixture file66- keep the old test temporarily67- mirror the assertions in a thin harness6869### 3) Keep the harness thin and deterministic7071The harness should mostly be:7273- parse fixture,74- iterate cases,75- call `run_case`,76- assert with stable case ids in failure output.7778### 4) Gate first, delete second7980Only remove the old “god test” after:8182- the fixture harness is green,83- failures are clearly case-id-addressable,84- reviewers can inspect the fixture diff without decoding harness internals.8586## Definition of done (what to leave behind)8788- Minimum deliverables (3-pack): Repro (fixture suite), Gate (nextest), Evidence (case-id failures). See `fret-skills-playbook`.89- Fixture suite has `schema_version` and stable case `id` keys.90- Harness is thin (parse → `run_case` → asserts) and does not depend on `cwd`.91- Failing output is case-id-addressable.92- Old matrix tests are removed only after the fixture harness is green and reviewed.9394## Evidence anchors9596- Fixture-driven test examples:97 - `ecosystem/fret-ui-shadcn/tests/web_vs_fret_layout.rs`98 - `ecosystem/fret-ui-shadcn/tests/data_grid_layout.rs`99 - `ecosystem/fret-ui-shadcn/tests/resizable_panel_group_layout.rs`100- Goldens (overview + conventions): `goldens/README.md`101- Layering boundaries: `tools/check_layering.py`102- Diagnostics scripts for procedural cases: `tools/diag-scripts/ui-gallery-intro-idle-screenshot.json`103- This skill’s reference:104 - `.agents/skills/fret-fixture-driven-harnesses/references/fixture-schema-and-harness.md`105106## Examples107108- Example: replace a growing matrix test with fixtures109 - User says: "This test file keeps growing—every change adds another case."110 - Actions: extract cases into `fixtures/*.json`, keep a thin harness, and make failures case-id-addressable.111 - Result: smaller diffs, fewer conflicts, clearer intent.112113## Common pitfalls114115- Using fixtures for procedural state machines.116- Making fixtures too clever (unstable IDs, floats everywhere, hard-to-diff shape).117- Letting the harness grow beyond parsing + `run_case` + asserts.118119## Troubleshooting120121- Symptom: fixtures depend on `cwd` and fail in CI.122 - Fix: load with `include_str!` + `env!("CARGO_MANIFEST_DIR")`.123- Symptom: fixtures are hard to review.124 - Fix: keep stable `id`s, prefer integers/enums, and split large suites by subsystem.125126## Related skills127128- `fret-diag-workflow`129- `fret-shadcn-source-alignment`130- `fret-boundary-checks`