โ Protest
Property-Based Testing for Rust - An ergonomic, powerful, and feature-rich property testing library with minimal boilerplate.
Features
- ๐ Ergonomic API - Test properties with closures, no boilerplate
- ๐ฏ Automatic Generator Inference - Smart type-based generator selection
- ๐ง Derive Macros -
#[derive(Generator)]for custom types - ๐ฆ Declarative Macros -
property!,assert_property!,generator! - โก Async Support - First-class async property testing
- ๐ Smart Shrinking - Automatic minimal counterexample finding
- ๐จ Fluent Builders - Chain configuration methods naturally
- ๐งช Common Patterns - Built-in helpers for mathematical properties
- ๐ Parallel Execution - Run tests in parallel for speed
- ๐ Statistics & Coverage - Track generation and test coverage
- ๐ญ Flexible - Works with any type, sync or async
Quick Start
Add Protest to your Cargo.toml:
[]
= { = "0.1", = ["derive"] }
Ultra-Simple Example
use *;
Ergonomic API Example
use *;
Attribute Macro Example
use property_test;
Custom Struct Example
use Generator;
API Styles
Protest offers multiple API styles - use what fits your needs:
1. Declarative Macros (Most Concise)
use *;
// Simple property test
property!;
// With configuration
property!;
// Assert style (panics on failure)
assert_property!;
2. Fluent Builder API (Most Flexible)
use *;
property
.iterations
.seed
.max_shrink_iterations
.run_with
.expect;
3. Attribute Macros (Most Integrated)
use property_test;
4. Direct API (Most Control)
use *;
;
let result = check;
assert!;
Common Property Patterns
Protest includes built-in helpers for common mathematical properties:
use *;
// Commutativity: f(a, b) == f(b, a)
commutative;
// Associativity: f(f(a, b), c) == f(a, f(b, c))
associative;
// Idempotence: f(f(x)) == f(x)
idempotent;
// Round-trip: decode(encode(x)) == x
round_trip;
// Inverse functions: f(g(x)) == x && g(f(x)) == x
inverse;
// Identity element: f(x, e) == x
has_identity;
// Monotonicity
monotonic_increasing;
// Distributivity
distributive;
Async Support
Full support for runtime-agnostic async property testing. Works with any async runtime (tokio, async-std, smol):
use *;
;
async
Note: Protest is runtime-agnostic - you bring your own async runtime. Add tokio, async-std, or smol to your dev-dependencies as needed.
Automatic Generator Inference
Protest automatically infers generators for common types:
use AutoGen;
// All primitive types
i32auto_generator;
Stringauto_generator;
boolauto_generator;
// Collections
Vec::auto_generator;
auto_generator;
// Tuples
<>auto_generator;
// Options
Option::auto_generator;
// Your custom types with #[derive(Generator)]
auto_generator;
Shrinking
When a property fails, Protest automatically finds the minimal counterexample:
property!;
// Fails with: Property failed with input 50 (shrunk from larger value)
// Focus on input: 50
Configuration
Extensive configuration options:
use *;
use Duration;
let config = TestConfig ;
Examples
The repository includes comprehensive examples:
basic_usage.rs- Getting startedergonomic_api_demo.rs- All ergonomic featurescustom_structs.rs- Custom types with deriveasync_properties.rs- Async testingadvanced_patterns.rs- Advanced techniques
Run examples:
Comparison with Other Libraries
| Feature | Protest | proptest | quickcheck |
|---|---|---|---|
| Ergonomic API | โ | โ | โ |
| Automatic Inference | โ | โ | Partial |
| Derive Macros | โ | โ | โ |
| Async Support | โ | โ | โ |
| Declarative Macros | โ | โ | โ |
| Fluent Builders | โ | Partial | โ |
| Pattern Helpers | โ | โ | โ |
| Shrinking | โ | โ | โ |
| Statistics | โ | Partial | โ |
Documentation
Full documentation is available on docs.rs.
Key Modules
protest::ergonomic- Ergonomic API (closures, builders, patterns)protest::primitives- Built-in generatorsprotest::generator- Generator trait and utilitiesprotest::property- Property trait and executionprotest::shrink- Shrinking infrastructureprotest::config- Configuration typesprotest::statistics- Coverage and statistics
Feature Flags
[]
= ["derive"]
= ["protest-derive"] # Derive macros
Protest has minimal dependencies and no required runtime dependencies. Async support is built-in and runtime-agnostic.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
Inspired by:
- proptest - Rust property testing
- QuickCheck - Original Rust QuickCheck
- Hypothesis - Python property testing
Roadmap
- More built-in generators
- Enhanced shrinking strategies
- Integration with more test frameworks
- Property test replay and persistence
- Coverage-guided generation
- Stateful property testing DSL
Made with โค๏ธ for the Rust community