# Testing Guide
## Test Pyramid
captchaforge uses a 5-tier test pyramid:
```
▲
/│\ Chaos (failure injection) ~5 tests
/ │ \ ─────────────────────────────────────────
/ │ \ Integration (real Chrome) ~8 tests
/ │ \ ─────────────────────────────────────────
/ │ \ Property (proptest) ~40 tests
/ │ \─────────────────────────────────────────
/ │ Snapshot (insta) ~10 tests
/ │ ────────────────────────────────────────
────────┴────── Unit (inline) ~40 tests
```
## Running Tests
### Fast tier (~10 seconds)
Unit tests, property tests, snapshot tests, chaos tests (no browser needed).
```bash
cargo test --lib
cargo test --test property_detect
cargo test --test property_solver
cargo test --test property_frame
cargo test --test property_behavior
cargo test --test snapshot_structures
cargo test --test chaos_resilience
```
### Integration tier (~2 minutes)
Real browser tests. Requires Chrome/Chromium installed.
```bash
# Run all integration tests
cargo test --test integration -- --ignored --test-threads=1
# Run a specific integration test
cargo test --test integration detect_turnstile_on_mock_page -- --ignored --test-threads=1
```
### Full suite (~5 minutes)
```bash
cargo test --workspace
```
### With coverage
```bash
cargo install cargo-llvm-cov
cargo llvm-cov --workspace --html --open
```
## Writing Property Tests
Add to `tests/property_*.rs`:
```rust
use captchaforge::detect::{is_captcha, CaptchaInfo, DetectedCaptcha};
use proptest::prelude::*;
proptest! {
#[test]
fn my_property(kind in any_detected_captcha()) {
let info = CaptchaInfo { kind, ..Default::default() };
// invariant to verify
prop_assert!(/* ... */);
}
}
```
Run with:
```bash
cargo test --test property_detect my_property -- --nocapture
```
## Writing Snapshot Tests
Add to `tests/snapshot_structures.rs`:
```rust
#[test]
fn snap_my_structure() {
let data = MyStruct { /* ... */ };
insta::assert_json_snapshot!(data);
}
```
After first run, review the `.snap` file in `tests/snapshots/` and commit it.
## Writing Chaos Tests
Add to `tests/chaos_resilience.rs`:
```rust
#[test]
fn my_chaos_test() {
// Test extreme inputs, edge cases, failure modes
// No browser needed, focus on panic prevention
}
```
## Fuzz Testing
```bash
cd fuzz
cargo fuzz run fuzz_detect -- -max_total_time=300
```
## CI Behavior
- PRs trigger: `ci.yml` (unit + property + lint + docs)
- Merges to `main` trigger: `ci.yml` + `bench.yml` + `coverage.yml`
- Weekly: `fuzz.yml` (30-min fuzz run)