| Crates.io | protest-proptest-compat |
| lib.rs | protest-proptest-compat |
| version | 1.1.0 |
| created_at | 2025-11-01 19:13:37.19863+00 |
| updated_at | 2025-11-02 17:29:25.468133+00 |
| description | Proptest compatibility layer for Protest - drop-in replacement for easy migration |
| homepage | |
| repository | https://github.com/shrynx/protest |
| max_upload_size | |
| id | 1912323 |
| size | 29,992 |
Migration helpers for transitioning from proptest to Protest.
This crate provides utilities and guidance to make migrating from proptest to Protest easier. Rather than being a drop-in replacement, it focuses on:
[dev-dependencies]
# Remove:
# proptest = "1.0"
# Add:
protest = "0.1"
protest-proptest-compat = "0.1" # For migration helpers
// Before:
use proptest::prelude::*;
// After:
use protest::*;
// or
use protest::ergonomic::*;
Before (Proptest):
proptest! {
#[test]
fn test_addition(a in 0..100i32, b in 0..100i32) {
assert!(a + b >= a);
assert!(a + b >= b);
}
}
After (Protest):
#[test]
fn test_addition() {
property!(generator!(i32, 0, 100), |(a, b)| {
a + b >= a && a + b >= b
});
}
Before (Proptest):
proptest! {
#[test]
fn reverse_twice_is_identity(v: Vec<i32>) {
let mut v2 = v.clone();
v2.reverse();
v2.reverse();
assert_eq!(v, v2);
}
}
After (Protest - Ergonomic API):
#[test]
fn reverse_twice_is_identity() {
property(|mut v: Vec<i32>| {
let original = v.clone();
v.reverse();
v.reverse();
v == original
})
.iterations(100)
.run()
.expect("property should hold");
}
Before (Proptest):
use proptest::strategy::Strategy;
fn user_strategy() -> impl Strategy<Value = User> {
(0..1000u32, "[a-z]{5,10}").prop_map(|(id, name)| {
User { id, name }
})
}
After (Protest):
use protest::Generator;
#[derive(Generator)]
struct User {
#[generator(range = "0..1000")]
id: u32,
#[generator(length = "5..10")]
name: String,
}
// Or manually:
struct UserGenerator;
impl Generator<User> for UserGenerator {
fn generate(&self, rng: &mut dyn RngCore, config: &GeneratorConfig) -> User {
User {
id: IntGenerator::new(0, 1000).generate(rng, config),
name: StringGenerator::new(5, 10).generate(rng, config),
}
}
}
Before (Proptest):
use proptest::option;
prop::option::of(0..100i32)
After (Protest with helpers):
use protest_proptest_compat::option_generator;
use protest::primitives::IntGenerator;
option_generator(IntGenerator::new(0, 100), 0.5) // 50% Some, 50% None
Before (Proptest):
use proptest::collection::vec;
vec(0..100i32, 0..10) // Vec with 0-10 elements
After (Protest with helpers):
use protest_proptest_compat::vec_generator;
use protest::primitives::IntGenerator;
vec_generator(IntGenerator::new(0, 100), 0, 10)
range_to_generatorConvert a proptest range to a Protest generator:
use protest_proptest_compat::range_to_generator;
let generator = range_to_generator(0, 100);
vec_generatorCreate a vector generator:
use protest_proptest_compat::vec_generator;
use protest::primitives::IntGenerator;
let generator = vec_generator(IntGenerator::new(0, 100), 5, 10);
option_generatorCreate an option generator with custom probability:
use protest_proptest_compat::option_generator;
use protest::primitives::IntGenerator;
let generator = option_generator(IntGenerator::new(0, 100), 0.7); // 70% Some
GeneratorAdapterWrap a Protest generator for easier use:
use protest_proptest_compat::GeneratorAdapter;
use protest::primitives::IntGenerator;
let adapter = GeneratorAdapter::new(IntGenerator::new(0, 100));
let value = adapter.generate(&mut rng);
proptest::prelude::* with protest::*proptest! macro - Convert to regular #[test] functions0..100i32 → generator!(i32, 0, 100)VecGenerator, etc.Generator traitprop_assert! → assert!prop_map - Use generator methods or custom generators| Proptest | Protest |
|---|---|
proptest! { #[test] fn ... } |
#[test] fn ... with property! or property() inside |
a in 0..100 |
generator!(i32, 0, 100) or manual generator |
| Concept | Proptest | Protest |
|---|---|---|
| Trait | Strategy |
Generator |
| Range | 0..100 |
IntGenerator::new(0, 100) |
| Vector | vec(strategy, size) |
VecGenerator::new(gen, min, max) |
| Option | prop::option::of(...) |
OptionGenerator::new(...) |
| Custom | impl Strategy |
impl Generator |
| Feature | Proptest | Protest |
|---|---|---|
| Iterations | ProptestConfig | .iterations(N) |
| Shrinking | Built-in | Built-in (automatic) |
| Mapping | .prop_map() |
Generator methods or custom impl |
| Filtering | .prop_filter() |
Preconditions in property |
After migration, you'll benefit from:
#[derive(Generator)] for custom typesSee the examples/ directory for:
migration_example.rs - Side-by-side comparisonsusing_helpers.rs - Using migration helper functionsRun examples with:
cargo run --example migration_example
cargo run --example using_helpers
A: No. This crate provides helpers and guidance for migration, but you'll need to update your test code. The migration is straightforward for most cases.
A: Yes! You can migrate gradually, keeping some tests in proptest while converting others to Protest.
prop_compose! macro?A: Use Protest's #[derive(Generator)] or implement the Generator trait manually for more control.
prop_assert! and prop_assume!?A: Use regular assert! for assertions. For assumptions (filtering), use preconditions in your property or generator logic.
A: Protest-extras provides RegexGenerator for regex-based string generation.
Found a migration pattern not covered here? Please open an issue or PR at the main Protest repository.
Licensed under the MIT license. See LICENSE for details.