
2,300 stars · Dual Apache-2.0 or MIT, named in the About sidebar on 28 October 2026 · 1.12.0, published to the Rust package registry on 10 October 2026, read from crates.io's API · Track this in Rising ↗
Generates random inputs to check that properties hold and shrinks failures to minimal examples, in Rust.
Radar check
What we found when we opened it. Every bar is one fact, with its date.
Last code pushed 10 Oct 2026, 17 days before this check.
Latest release 0.9.6 on 11 Apr 2020.
Public since June 2017, a little over 9 years.
2,271 stars and 240 forks.
20 commits and 3 new issues in the last 90 days.
102 contributors. 9 pull requests merged in 90 days.
No security policy file says how to report a problem. No published security advisories.
How the bars are scored
- Alive. Days since the last code push: a week or less 100, a month 90, three months 70, six months 50, a year 30, eighteen months 15, older 0.
- Releases. Age of the latest GitHub release, on a similar scale; no bar when the project publishes no releases.
- Maturity. Age of the project: eight years 100, five 90, three 70, two 55, one 40, six months 25, younger 10.
- Adoption. Stars on a log scale: 100,000 stars is 100, 10,000 is 80, 1,000 is 60, 100 is 40.
- Activity. Commits in the last 90 days: 300 or more 100, 100 85, 30 65, 10 45, any 25.
- Community. People who have contributed: 100 or more 100, 30 80, 10 60, 5 40, 2 25, one 10.
- Security. A published security policy 80, none 40; published advisories are listed, not scored.
Checked by Repo Radar on 28 Oct 2026 from the repository on GitHub. Covered in Edition 64.
▶Repo detailsthe review · specs · pros & cons · install
What it does
It is a library added to a project's test dependencies. You write a rule rather than an example: for any two numbers, sorting then reversing gives the same answer as reversing then sorting, say. You then describe the inputs with what the library calls a strategy, which can be as simple as "any whole number" or built up into something complex such as "a list of between one and ten records, each with a name of at most twenty letters". It generates values from that description, runs the test for each, and if one fails it begins shrinking: halving numbers, shortening lists, removing fields, until any further simplification makes the test pass again. The failing case is saved to a file in the project so the same input is tried first on every later run, which turns a lucky catch into a permanent test. Generation and shrinking are defined per value rather than per type, which is what lets a strategy be assembled from parts. The project is clear about the limits: it cannot explore an input space exhaustively, and its README says property testing is "extremely unlikely to find single-value edge cases in a large space", so ordinary tests are still needed alongside it. The README also says the crate "mainly sees passive maintenance", which is the project's own wording.
Why it matters
Who it suits. Anyone writing Rust code that parses, converts or compares things, because those are the places where the mistakes live in inputs nobody imagined: an empty list, a string with no letters in it, two values that happen to be equal. It also suits anyone who has just fixed a bug and wants to be sure the whole family of that bug is gone rather than the one case reported. Skip it if the code is mostly wiring between other systems, where the interesting failures are about the systems rather than the values.
Verdict. Worth an afternoon on the two or three functions in a project that actually transform data, and not worth applying everywhere. The shrinking is the part that earns it: a random failure is noise, and a failure shrunk to "an empty list" or "the number zero" is a bug report that explains itself. Three things to know. The tests are slower than ordinary ones by their nature, so they belong in the slower part of a test run. Writing a good description of the inputs is a real skill, and a sloppy one generates values that are either all alike or all invalid. And the "passive maintenance" note deserves to be read as the project wrote it rather than as a warning sign: version 1.12.0 was published to the Rust package registry on 10 October 2026, eighteen days before this was written. BurntSushi/quickcheck is the simpler alternative in the same language, and HypothesisWorks/hypothesis is where this whole approach is most developed, in Python.
Summary (Key Points)from the README
Key features
- Per-value strategies: Generation and shrinking are defined per value rather than per type, so you can define many different strategies for the same type.
- Automatic minimal shrinking: When a failing input is found, proptest reduces it to a much simpler case, such as reducing a failing date to 0000-10-01.
- Failure persistence: Failing cases are saved in a `proptest-regressions` directory, which the README recommends adding to source control.
- Regex-driven string generation: Strings can be generated from regular expressions, such as `\\PC*` for arbitrary non-control characters or `\\d{4}-\\d{2}-\\d{2}` style patterns for a fixed format.
- Range and expression strategies: Any `Strategy` can be used as a generator, including integer ranges like `0..100`.
- Composition with `prop_map`: You can build a tuple of components and map it into a struct, without hand-written bidirectional mappings.
- Constraint-aware generation: Strategies avoid generating or shrinking to values that violate simple constraints, which reduces input rejections.
- Configurable test runs: The `proptest!` macro accepts configuration, such as the number of test cases to generate.
Important
- Passive maintenance: The crate is described as fairly close to feature-complete, with no substantial architectural changes in quite some time, and it mainly sees passive maintenance.
- MSRV of 1.88: The current minimum supported Rust version is 1.88, and the README promises it will not exceed a stated bound (the text reads "7"), though it may be lower in practice.
- Breaking MSRV changes: Changing the MSRV policy in a backwards-incompatible way would be a major version bump.
- Slower than QuickCheck for complex values: Generating complex values can be up to an order of magnitude slower than in QuickCheck, because proptest keeps intermediate states for its richer shrinking.
- Random sampling limits: Only a random portion of the input space is explored, so single-value edge cases in large spaces are very unlikely to be found; hand-picked unit tests are still needed.
- Strategy design matters: Overly broad strategies, such as `.{1,4096}`, may be good for fuzzing but unlikely to produce inputs that reach deeper code.
Written by an AI model from the project’s README; not part of the review, and it can be wrong.
- Shrinks a failure to the smallest example, which usually explains the bug on sight.
- Saves failing cases to a file, so a one-off catch becomes a permanent test.
- Input descriptions are built from parts, so a complex shape can be described precisely.
- Noticeably slower than ordinary tests, so it does not belong in a fast feedback loop.
- Writing a good input description takes practice, and a poor one finds nothing.
- The project says it sees passive maintenance, so expect few new capabilities.
- BurntSushi/quickcheck
The same approach for the same language: simpler to start with, and less able to describe awkward inputs.
Track this in Rising ↗
HypothesisWorks/hypothesisThe most developed library of this kind, for Python, and the one that inspired this.
Track this in Rising ↗- dubzzz/fast-check
The same approach for JavaScript and TypeScript, the natural choice for a web project.
Track this in Rising ↗
cargo add proptest --dev