用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/tomevault-io/skills-registry --skill tdd-rust命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
| Use when this capability is needed.
> Use when this capability is needed.
Review architecture and API design for the vfs-s3 project. Use when the user mentions @architect, asks to review an issue's design, discuss module boundaries, API shape, or architectural decisions for vfs-s3. Also trigger when the user wants to create an ADR (Architecture Decision Record) or evaluate a technical approach for the project. Intended for dispatch from Codex automation or Claude routines; GitHub trigger phrase: @vfs-s3-bot please prepare design doc Use when this capability is needed.
基于 SOC 职业分类
正在显示 SKILL.md
| name | tdd-rust |
| description | Enforce strict Test-Driven Development: **Red → Green → Refactor** Use when this capability is needed. |
Enforce strict Test-Driven Development: Red → Green → Refactor
#[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)
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
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).(Utc::now),
})
}
Final verification:
cargo test test_parse_session_metadata
cargo clippy --all-targets
// 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
}
}
// 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);
}
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);
}
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
}
# 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);
}
}
Before EVERY commit:
cargo fmt --all # Format code
cargo clippy --all-targets # Lint
cargo test --all # All tests pass
# 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
❌ 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
Source: florianbruniaux/ccboard — distributed by TomeVault.