florianbruniaux/ccboard · Archived

tdd-rust

Test-Driven Development workflow for Rust - write test first, watch it fail, implement minimal code

First seen Mar 23, 2026

Installation

$ npx skills add florianbruniaux/ccboard --skill tdd-rust

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from florianbruniaux/ccboard.

npx skills add florianbruniaux/ccboard

Browse all from florianbruniaux/ccboard

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 75
License LICENSE
Default branch main
Open issues 20
Status Archived

Skill metadata

Parsed from SKILL.md frontmatter.

Version1.0.0description: Test-Driven Development workflow for Rust — wr
Allowed toolsRead, Write, Edit, Bash, Grep, Glob

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 5,305 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 3 installs

SKILL.md

TDD Workflow for Rust Projects

Enforce strict Test-Driven Development: Red → Green → Refactor

Workflow Steps

1. RED: Write failing test first

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_parse_session_metadata() {
        let path = Path::new("tests/fixtures/session.jsonl");
        let metadata = extract_metadata(path).unwrap();

        assert_eq!(metadata.message_count, 42);
        assert!(metadata.first_timestamp < metadata.last_timestamp);
    }
}

Run test to verify failure:

cargo test test_parse_session_metadata
# Expected: FAILED (function doesn't exist yet)

2. GREEN: Implement minimal code to pass

pub fn extract_metadata(path: &Path) -> anyhow::Result<SessionMetadata> {
    // Minimal implementation
    Ok(SessionMetadata {
        message_count: 42, // Hardcoded for first pass
        first_timestamp: Utc::now(),
        last_timestamp: Utc::now(),
        // ...
    })
}

Run test again:

cargo test test_parse_session_metadata
# Expected: PASSED

3. REFACTOR: Improve implementation

pub fn extract_metadata(path: &Path) -> anyhow::Result<SessionMetadata> {
    let file = File::open(path).context("Failed to open session file")?;
    let reader = BufReader::new(file);

    let mut first_line: Option<SessionLine> = None;
    let mut last_line: Option<SessionLine> = None;
    let mut count = 0;

    for line in reader.lines() {
        let line = line?;
        if let Ok(parsed) = serde_json::from_str::<SessionLine>(&line) {
            if first_line.is_none() {
                first_line = Some(parsed.clone());
            }
            last_line = Some(parsed);
            count += 1;
        }
    }

    Ok(SessionMetadata {
        message_count: count,
        first_timestamp: first_line.map(|l| l.timestamp).unwrap_or_else(Utc::now),
        last_timestamp: last_line.map(|l| l.timestamp).unwrap_or_else(Utc::now),
        // ...
    })
}

Final verification:

cargo test test_parse_session_metadata
cargo clippy --all-targets

Test Organization

Unit Tests (embedded in module)

// src/parsers/session_index.rs
pub fn extract_metadata(path: &Path) -> anyhow::Result<SessionMetadata> {
    // Implementation
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_extract_metadata_valid_file() {
        // Test happy path
    }

    #[test]
    fn test_extract_metadata_malformed_lines() {
        // Test error handling
    }
}

Integration Tests (tests/ directory)

// tests/integration_test.rs
use ccboard_core::store::DataStore;

#[tokio::test]
async fn test_initial_load() {
    let store = DataStore::new();
    let report = store.initial_load().await.unwrap();
    assert!(report.stats_loaded);
}

Fixtures Management

Store sanitized test data in tests/fixtures/:

tests/
├─ fixtures/
│  ├─ stats-cache.json
│  ├─ session.jsonl
│  ├─ settings.json
│  └─ agent.md
└─ integration_test.rs

Load fixtures in tests:

#[test]
fn test_parse_stats() {
    let fixture = include_str!("../tests/fixtures/stats-cache.json");
    let stats: StatsCache = serde_json::from_str(fixture).unwrap();
    assert!(stats.total_input_tokens > 0);
}

Async Tests

use tokio::test;

#[tokio::test]
async fn test_parallel_session_scan() {
    let store = DataStore::new();

    // Test concurrent operations
    let tasks = vec![
        store.reload_stats(),
        store.update_session(path),
    ];

    let results = futures::future::join_all(tasks).await;
    // Assertions
}

Property-Based Testing (Optional)

# Cargo.toml
[dev-dependencies]
proptest = "1"
use proptest::prelude::*;

proptest! {
    #[test]
    fn test_session_parse_never_panics(s in "\\PC*") {
        // Should handle any input without panicking
        let _ = serde_json::from_str::<SessionLine>(&s);
    }
}

Pre-Commit Checklist

Before EVERY commit:

cargo fmt --all              # Format code
cargo clippy --all-targets   # Lint
cargo test --all             # All tests pass

Command Shortcuts

# Run specific test
cargo test test_name

# Run tests with output
cargo test -- --nocapture

# Run tests in module
cargo test parsers::

# Watch mode
cargo watch -x test

# Coverage (requires cargo-tarpaulin)
cargo tarpaulin --out Html

Anti-Patterns

❌ DON'T skip the RED phase (test must fail first) ❌ DON'T write implementation before test ❌ DON'T use .unwrap() in tests - use .expect("meaningful message") ❌ DON'T commit without running tests

✅ DO write test first, watch it fail ✅ DO implement minimal code to pass ✅ DO refactor after green ✅ DO use descriptive test names ✅ DO test both success and error paths