noprop 0.0.2

Imperative property-based testing library with no dependencies, no macros, no unsafe, and no implicit I/O
Documentation
noprop
======

[![noprop](https://img.shields.io/crates/v/noprop.svg)](https://crates.io/crates/noprop)
[![Documentation](https://docs.rs/noprop/badge.svg)](https://docs.rs/noprop)
[![Actions Status](https://github.com/sile/noprop/workflows/CI/badge.svg)](https://github.com/sile/noprop/actions)
![License](https://img.shields.io/crates/l/noprop)

An imperative property-based testing library for Rust.

- No dependencies
- No macros
- No `unsafe` code (`#![forbid(unsafe_code)]`)
- No implicit I/O — seeds are always caller-supplied, so every run is fully reproducible
- Imperative API — properties are plain `Fn(&mut TestCaseContext) -> Result<(), Box<dyn Error>>` closures that use ordinary Rust control flow (`if` / `match` / `for`) instead of combinator DSLs
- Automatic value trace — each `noprop::sample_*` call is recorded at its source location and surfaced on failure, so the failing input is visible without extra plumbing

Targeted search (`Runner::run_targeted`) is available behind the same
imperative API; its design is documented in
[docs/targeted-search.md](https://github.com/sile/noprop/blob/main/docs/targeted-search.md).

Example
-------

```rust
#[test]
fn addition_is_commutative() -> noprop::Result<()> {
    noprop::Runner::new(0xDEAD_BEEF, 1024).run(|ctx| {
        let a = noprop::sample_u32(ctx);
        let b = noprop::sample_u32(ctx);
        assert_eq!(a.wrapping_add(b), b.wrapping_add(a));
        Ok(())
    })?;
    Ok(())
}
```

Status
------

Early development (`v0.0.x`). API is unstable and may change without notice.