Proptest for Rust: A Complete Guide with Examples

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

What is Proptest and why is it needed?

\n\n

Proptest is a powerful library for property-based testing in the Rust language. Unlike traditional unit testing, where you manually specify specific input data and expected results, property-based testing allows you to describe properties that your program must satisfy for any valid input data. The library automatically generates many random test cases and checks whether the specified properties hold.

\n\n

Why is this needed?

\n
    \n
  • Detecting hidden bugs: Random data often finds edge cases that the developer didn't even think of.
  • \n
  • Reducing test code volume: Instead of writing dozens of examples, you write one property.
  • \n
  • Automatic shrinking: If a test fails, Proptest automatically tries to find the minimal set of input data that reproduces the error.
  • \n
  • Documenting specifications: Properties are formal, verifiable statements about code behavior.
  • \n
\n\n

Proptest is inspired by the QuickCheck library from Haskell, but adapted to Rust's specifics, including working with ownership, borrowing, and traits.

\n\n

Installation

\n\n

Proptest is a Rust library, so it is installed via the Cargo package manager. Add it to the [dev-dependencies] section of your Cargo.toml file:

\n\n
[dev-dependencies]\nproptest = "1.4"
\n\n

After that, run cargo build or cargo test to download and compile the library. Proptest is used only during testing, so it does not increase the size of your final binary.

\n\n

For working with asynchronous code (tokio, async-std), additional configuration may be required, but in most cases, the standard installation is sufficient.

\n\n

Quick Start with Code Example

\n\n

Let's write a simple test that checks whether the reverse function (reversing a string) is an involution: applying it twice returns the original string.

\n\n
// src/lib.rs\npub fn reverse(s: &str) -> String {\n    s.chars().rev().collect()\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use proptest::prelude::*;\n\n    proptest! {\n        #[test]\n        fn test_reverse_involution(s in ".*") { // ".*" — any string\n            let reversed = reverse(&s);\n            let double_reversed = reverse(&reversed);\n            prop_assert_eq!(s, double_reversed);\n        }\n    }\n}
\n\n

Run the tests: cargo test. Proptest will generate 256 random strings (by default) and check that the property holds. If a test fails, you will see a message with the minimal reproducing example.

\n\n

Main Methods and Functions

\n\n

Below are the key components of Proptest. For each, a description, parameters, and an example are provided.

\n\n

1. proptest! — macro for defining tests

\n

Description: The main macro that runs property-based tests. It takes a block with test functions and automatically generates input data.

\n

Parameters: Inside the macro, you define tests with the #[test] attribute. Input data is specified as param in strategy.

\n

Example:

\n
proptest! {\n    #[test]\n    fn test_addition_commutative(a in 0..100i32, b in 0..100i32) {\n        prop_assert_eq!(a + b, b + a);\n    }\n}
\n\n

2. prop_assert! and prop_assert_eq! — assertions

\n

Description: Analogues of the standard assert!

Recommendations