test-runner

Execute and manage Rust tests for the self-learning memory project.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "test-runner" with this command: npx skills add d-o-hub/rust-self-learning-memory/d-o-hub-rust-self-learning-memory-test-runner

Test Runner

Execute and manage Rust tests for the self-learning memory project.

Test Categories

Category Command (preferred) Fallback Scope

Unit cargo nextest run --lib

cargo test --lib

Individual functions

Integration cargo nextest run --test '*'

cargo test --test '*'

End-to-end workflows

Doc cargo test --doc

(nextest unsupported) Documentation examples

All cargo nextest run --all

cargo test --all

Complete validation

Mutation cargo mutants -p memory-core

— Test effectiveness

Snapshot cargo insta test

— Output regression

Execution Strategy

Step 1: Quick Check (Unit Tests)

cargo nextest run --lib

  • Fast feedback (< 30s), per-test process isolation

  • Catch basic logic errors

Step 2: Integration Tests

cargo nextest run --test '*'

  • Tests database interactions

  • Requires Turso/redb setup

Step 3: Full Suite

cargo nextest run --all cargo test --doc # doctests separately (nextest limitation)

  • Complete validation before commit

Step 4: Mutation Testing (Periodic)

cargo mutants -p memory-core --timeout 120 --jobs 4 -- --lib

  • Verifies test suite catches real bugs

  • Run nightly or before releases (ADR-033)

Troubleshooting

Async/Await Issues

Symptom: Test hangs

#[tokio::test] async fn test_async() { let result = async_fn().await; // Don't forget .await }

Database Connection

Symptom: Connection refused

  • Check TURSO_URL, TURSO_TOKEN

  • Use test database

Race Conditions

Symptom: Intermittent failures

cargo test -- --test-threads=1

redb Lock Errors

Symptom: "Database is locked"

  • Use separate DB per test

  • Close transactions promptly

Coverage

cargo install cargo-llvm-cov cargo llvm-cov --html --output-dir coverage

Best Practices

  • Isolation: Each test independent

  • Cleanup: Remove test data

  • Speed: < 1s per unit test

  • Naming: test_<function><scenario><expected>

  • AAA pattern: Arrange-Act-Assert in every test

  • Single responsibility: Each test verifies ONE behavior

Advanced: Async Testing Patterns

// Time-based testing (paused clock) #[tokio::test(start_paused = true)] async fn test_timeout_behavior() { let start = tokio::time::Instant::now(); tokio::time::sleep(Duration::from_secs(5)).await; assert!(start.elapsed().as_millis() < 100); }

// Concurrent operations #[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn test_concurrent_episodes() { let memory = Arc::new(setup_memory().await); let handles: Vec<> = (0..10).map(|i| { let mem = memory.clone(); tokio::spawn(async move { mem.start_episode(format!("Task {}", i), ctx, type).await }) }).collect(); let results = futures::future::join_all(handles).await; assert_eq!(results.len(), 10); }

Common Async Pitfalls

Bad Good

std::thread::sleep()

tokio::time::sleep().await

memory.start_episode()

memory.start_episode().await

Single-threaded for concurrency multi_thread runtime

nextest Profiles (.config/nextest.toml)

[profile.default] retries = 0 slow-timeout = { period = "60s", terminate-after = 2 } fail-fast = false

[profile.ci] retries = 2 slow-timeout = { period = "30s", terminate-after = 3 } failure-output = "immediate-final" junit.path = "target/nextest/ci/junit.xml"

[profile.nightly] retries = 3 slow-timeout = { period = "120s", terminate-after = 2 }

cargo nextest run # default profile cargo nextest run --profile ci # CI with retries + JUnit cargo nextest run --profile nightly # nightly with extended timeouts

Snapshot Testing (insta)

#[test] fn test_mcp_tool_response() { let response = build_tool_response("search_patterns", &params); insta::assert_json_snapshot!(response); }

cargo insta test # run snapshot tests cargo insta review # accept/reject changes

Property-Based Testing

proptest! { #[test] fn test_episode_id_uniqueness( tasks in prop::collection::vec(any::<String>(), 1..100) ) { let rt = tokio::runtime::Runtime::new().unwrap(); rt.block_on(async { let memory = setup_memory().await; let mut ids = HashSet::new(); for desc in tasks { let id = memory.start_episode(desc, ctx, type_).await; prop_assert!(ids.insert(id)); } }); } }

Advanced: Episodic Memory Testing

#[tokio::test] async fn test_complete_episode_lifecycle() { let memory = setup_memory().await; let id = memory.start_episode("Test task", ctx, TaskType::CodeGen).await; memory.log_execution_step(id.clone(), step1).await; memory.complete_episode(id.clone(), TaskOutcome::Success, None).await?; let episode = memory.get_episode(&id).await?; assert_eq!(episode.outcome, TaskOutcome::Success); }

Performance Targets

Operation Target Actual

Episode Creation < 50ms ~2.5 µs

Step Logging < 20ms ~1.1 µs

Pattern Extraction < 1000ms ~10.4 µs

Memory Retrieval < 100ms ~721 µs

References

  • ADR-033: Modern Testing Strategy

  • TESTING.md — Full testing guide

Consolidated from these former skills (preserved in _consolidated/ ):

  • test-optimization — cargo-nextest, property testing, benchmarking

  • quality-unit-testing — AAA pattern, naming conventions, test quality

  • rust-async-testing — tokio test patterns, time-based testing

  • episodic-memory-testing — episode lifecycle, pattern extraction, reward scoring tests

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

context-retrieval

No summary provided by upstream source.

Repository SourceNeeds Review
General

rust-async-testing

No summary provided by upstream source.

Repository SourceNeeds Review
General

build-rust

No summary provided by upstream source.

Repository SourceNeeds Review
General

release-guard

No summary provided by upstream source.

Repository SourceNeeds Review