Crate contrafact

Source
Expand description

A trait for highly composable constraints (“facts”) which can be used both to verify data and to generate arbitrary data satisfying those constraints.

This crate is mainly intended for use in writing tests, and in particular for generating meaningful fixture data. By defining composable, reusable constraints, they can be mixed and matched to handle the specific use cases of your tests. By defining what you need from a fixture rather than simply writing the fixture you need, the hope is that you save yourself duplicated effort over time.

§Example

The following example defines a simple struct S with two fields, and a simple Fact (constraint) about S which says that S::x must always equal 1. This Fact, like all Facts, can be used both to verify that an instance of S meets the constraint, or to generate new instances of S which meet the constraint.

use contrafact::{Fact, facts::{eq, lens1}};
use arbitrary::{Arbitrary, Unstructured};

#[derive(Debug, Clone, PartialEq, Arbitrary)]
struct S {
    x: u32,
    y: u32,
}

let mut fact = lens1("S::x", |s: &mut S| &mut s.x, eq(1));

assert!(fact.clone().check(&S {x: 1, y: 333}).is_ok());
assert!(fact.clone().check(&S {x: 2, y: 333}).is_err());

// NB: don't actually construct a Generator this way! See the docs for [[`Generator`]].
let mut g = contrafact::utils::random_generator();
let a = fact.build(&mut g);
assert_eq!(a.x, 1);

§Things to know

The above example composes together existing Facts provided by this crate. You can also define your own facts by hand by implementing the Fact trait. TODO: example of this.

contrafact leans heavily on the arbitrary crate for generating arbitrary data. Get to know this library, because you will need to implement Arbitrary for any type you wish to write a Fact about.

Facts can be used to check if a constraint is matched via Fact::check() or [check_seq], and also to build new values via Fact::build and [build_seq]. Building values requires the use of arbitrary::Unstructured.

Facts can also be stateful, such that the constraint changes while checking or building a sequence. TODO: example of stateful fact.

Facts can be easily “horizontally” composed together through the facts! macro, which boxes each Fact and lumps them together as trait objects, applying each fact one after the other.

Facts can be “vertically” composed together through the [lens] and prism combinators, which allow you to lift a Fact about one type into a Fact about another type.

See the Functions documentation for more examples and detailed instructions about each Fact defined by this crate.

Re-exports§

pub use arbitrary;
pub use either;
pub use facts::*;

Modules§

facts
Some built-in implementations of some useful facts
utils
Helpers

Macros§

facts
Convenience macro for creating a collection of Facts of different types. The Facts will be composed into a nested series of [AndFact] which causes all facts to be applied in sequence. The collection of Facts is also a Fact.

Structs§

Generator
Generators are used to generate new values and error messages.

Enums§

Check
The result of a check operation, which contains a failure message for every constraint which was not met.
ContrafactError
Errors caused by bugs in Facts, Generators, or contrafact itself
MutationError
Errors which can occur during a mutate() call

Traits§

Fact
A declarative representation of a constraint on some data, which can be used to both make an assertion (check) or to mold some arbitrary existing data into a shape which passes that same assertion (mutate)
MutationExt
Adds a helpful method to MutationResults
State
The trait bounds for the State of a Fact
Target
The trait bounds for the target of a Fact

Functions§

lambda
Create a fact from a bare function which specifies the mutation. Can be quicker to experiment with ideas this way than to have to directly implement the Fact trait
lambda_unit
Create a lambda with unit state

Type Aliases§

ContrafactResult
Alias
Failure
A failure is the reason why some data does not conform to a given Fact
Mutation
Alias