BurntSushi / quickcheck

Automated property based testing for Rust (with shrinking).
The Unlicense
2.32k stars 144 forks source link

Add a convenience type for properties involving equivalence #281

Open neithernut opened 3 years ago

neithernut commented 3 years ago

This type was originally motivated by observing that a class of properties will involve a pseudo-identity followed by a check for equivalence between its input and output. A generalization of would be properties which are defined by the equivalence check, only. See #280.

For this class, we usually want to know how those two values differ, rather than only that they do. Test-authors may thus write tests like the following in order to include those values in a failure report:

fn revrev(xs: Vec<usize>) -> TestResult {
    let rev: Vec<_> = xs.clone().into_iter().rev().collect();
    let revrev: Vec<_> = rev.into_iter().rev().collect();
    if xs == revrev {
         TestResult::passed()
     } else {
         TestResult::error(format!("Original: '{:?}', Identity: '{:?}'", xs, revrev))
     }
}

This change introduces a convenience type which encapsulates the equivalence check as well as the error message generation. Using it, the above test could be written as:

fn revrev(xs: Vec<usize>) -> Equivalence<Vec<usize>> {
    let rev: Vec<_> = xs.clone().into_iter().rev().collect();
    let revrev: Vec<_> = rev.into_iter().rev().collect();
    Equivalence::of(xs, revrev)
}