Files
clawmates/skills/rust/cargo-test-driven-development.md
T
Omar SobhandClaude Opus 4.7 7b23f61632
ci / gates (push) Successful in 4s
ci / frontend (push) Successful in 25s
ci / rust (push) Failing after 3m41s
ci / e2e (push) Skipped
ci / publish (push) Skipped
slice 3.5c: seed 15 built-in skills across the 6 stacks
Hand-authored skill catalog anchored to real 2026-07 versions:
  - Rust 1.97.1 (stable), edition 2024
  - React 19.2.7, Server Components + Actions
  - TailwindCSS 4.3.3 (CSS-first config, Oxide engine)
  - three.js r185 (WebGPURenderer stable, BatchedMesh matured)
  - React Native 0.86 / Expo SDK 54+ (New Architecture default)
  - cargo-nextest 0.9.140, gitleaks 8.20+, cargo-audit 0.21+
  - Postgres 17 (18 in beta, don't rely on)
  - CUDA Blackwell, Metal Apple7+, ROCm CDNA3

Ships 15 skills across the categories:
  foundation/  workspace-repo-commit-protocol
               small-focused-commits
               tdd-red-green-refactor
               code-review-checklist
               int-xx-marker-protocol
               decompose-int-items
  rust/        write-rust-current-edition
               rust-error-handling
               cargo-test-driven-development
               rust-async-tokio-idioms
  backend/     postgres-migrations-forward-only
               postgres-index-selection
               api-pagination-day-1
  frontend/    react-19-server-components
               tailwind-v4-idioms
               component-4-state-model
  mobile/      expo-managed-vs-bare
               rn-flashlist-perf
  gpu/         gpu-coalescing-and-occupancy
               roofline-model
  threejs/     threejs-perf-and-teardown
  security/    cargo-audit-workflow
               secret-scanning-gitleaks

skills_loader.rs walks skills/**/*.md, parses YAML frontmatter
(name, description, when_to_use, tags), upserts via
skills_catalog::upsert_builtin. Idempotent per boot — bumps version
+ appends skill_versions row ONLY when body changes. Deterministic
sha256-derived ids so builtins are stable across boots.

Dockerfile copies skills/ to /etc/clawmates/skills. Server boot
task spawns loader alongside team_template_loader.

Follow-ups (Slice 3.5c continuation, future PRs):
  - 20-30 more skills (duckdb, shadcn composition, a11y, WebGPU
    migration, metal frame capture, rocprof, deep gitea forge
    integration, semgrep rulepacks)
  - Bind skills to team template roles (add [role.skills] refs to
    templates/teams/*.toml + wire template_role_skills population
    in team_template_loader)

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-07-19 13:55:44 -07:00

62 lines
3.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: cargo-test-driven-development
description: The `cargo nextest run` workflow for Rust TDD — fast, parallel, isolates flakes. Falls back to `cargo test` when nextest isn't installed.
when_to_use: You're the tester role, or coder role in the RED phase of TDD, on a Rust codebase.
tags: [rust, testing, tdd, versioned]
---
# Cargo TDD workflow
## Runner
**Primary: `cargo nextest run` (0.9.140 as of 2026-07).** Why over `cargo test`:
- Parallel process isolation — one panicking test doesn't taint others.
- Structured, greppable output.
- `--retries N` policy for flake-tolerance without hiding real failures.
- Per-test timeouts.
Install: `cargo install cargo-nextest --locked` in the runtime image; CI runs `cargo nextest run --profile ci`.
## The RED-GREEN loop (Rust flavor)
1. **RED — write the failing test.**
```rust
#[tokio::test]
async fn workspace_scoped_get_rejects_cross_workspace() {
let pool = testkit::pool().await;
let mine = seed_workspace(&pool).await;
let theirs = seed_workspace(&pool).await;
let row = insert_row(&pool, theirs).await;
assert!(get(&pool, row.id, mine).await.unwrap().is_none());
}
```
Run: `cargo nextest run workspace_scoped_get_rejects_cross_workspace`. Confirm the test fails because the fn doesn't exist yet or because behavior is missing.
2. **GREEN — minimal implementation.** Hardcode if that's what the ONE test asks for. Trust that the NEXT test will force you to generalize.
3. **REFACTOR under green.** Extract, rename, tighten. Re-run after each keystroke that could break something. `cargo nextest run <fn_name>` on the specific test is faster than the whole suite.
## Speed tricks
- **`cargo nextest run -j 8`** — parallelize across cores.
- **`cargo nextest run --no-fail-fast`** — see all failures in one pass, not just the first.
- **`cargo nextest run -E 'test(foo)'`** — filter expression language, more powerful than a substring.
- **`cargo check --tests`** before running — catches type errors ~10× faster than compiling test binaries.
## Coverage
- **`cargo llvm-cov nextest`** — nextest under llvm-cov instrumentation. Reports per-file line coverage.
- CI enforces ≥90% on changed lines. Locally: `cargo llvm-cov nextest --html && open target/llvm-cov/html/index.html`.
## Integration tests that hit real infra
- Postgres via `testcontainers` — spins a fresh container per test suite. NEVER mock the DB when the test's job is to prove a query.
- HTTP via `axum::Router` + `tower::ServiceExt::oneshot` — driver is in-process, no port needed.
- Docker via `bollard` mock or a `#[ignore]` guarded live test.
## Anti-patterns
- **Snapshot-only test files.** A snapshot proves nothing structural. Pair with real assertions.
- **`#[ignore]`d tests that stay ignored.** Ignore is a debt marker — file the ticket to fix and put the ticket ID in the ignore reason.
- **Testing panics with `should_panic` when a `Result::Err` would do.** Panics on the happy path of a test framework are user-hostile output.