Testing Philosophy
The Hierarchy
Tests are prioritized by the strength of the guarantee they provide:
- Determinism tests — Same seed + same input = bit-identical output. These are the proof that the system works. Highest priority.
- Property-based tests —
proptestgenerates random inputs and verifies invariants hold for all of them. Catches edge cases humans miss. - Snapshot tests —
instafor serialization formats (WARC++, JSON, index entries). Snapshots are reviewed artifacts. - Integration tests — Real HTTP via
wiremock, real storage backends, real index queries. - Unit tests — Standard
#[test]for isolated logic.
No Mocking Core Interfaces
The storage layer, index, and envelope are the system’s integrity boundaries. Never mock them. Use real implementations with in-memory backends:
#![allow(unused)]
fn main() {
// Correct: real implementation, in-memory backend
let store = InMemoryBlobStore::new();
let index = InMemoryIndex::new();
// Wrong: mocked storage that always returns Ok
// let store = MockBlobStore::new(); // DON'T
}
Test Naming
test_{what}_{condition}_{expected_outcome}
Examples:
test_frontier_with_same_seed_produces_identical_ordertest_artifact_hash_changes_when_content_differstest_storage_put_get_roundtrip_preserves_content
Adversarial Testing
Every adversarial input must produce a classified error, never a panic or silent corruption:
- Malformed HTTP responses
- Truncated connections mid-transfer
- DNS resolution failures
- TLS certificate anomalies
- Content that attempts to exploit parsers (polyglot files, zip bombs)
Test Coverage
301 tests across 21 test files, covering all 15 crates. The simulation framework proves determinism at 10,000 pages with zero divergence.