# 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, eq, lens};
use arbitrary::{Arbitrary, Unstructured};
#[derive(Debug, Clone, PartialEq, Arbitrary)]
struct S {
x: u32,
y: u32,
}
let mut fact = lens("S::x", |s: &mut S| &mut s.x, eq("must be 1", 1));
assert!(fact.check(&S {x: 1, y: 333}).is_ok());
assert!(fact.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).unwrap();
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;`

## Modules

- Helpers

## Macros

- Convenience macro for creating a collection of
`Fact`

s of different types. Each Fact will be boxed and added to a Vec as a trait object, with their types erased. The resulting value also implements`Fact`

.

## Structs

- A brute-force fact. Use
`brute()`

to construct. - Generators are used to generate new values and error messages.
- A fact which uses a lens to apply another fact. Use
`lens()`

to construct. - A fact which is mapped from the data to be checked/mutated. Use
`mapped`

to construct. - A fact which uses a prism to apply another fact. Use
`prism()`

to construct.

## Enums

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

call

## Traits

- The trait bounds for the subject of a 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)
- Adds a helpful method to MutationResults

## Functions

- A constraint which is always met
- A constraint defined only by a predicate closure. Mutation occurs by brute force, randomly trying values until one matches the constraint.
- A version of
`brute`

whose closure returns a Result - Build a sequence from scratch such that all Facts are satisfied. Each Fact will run
`Fact::advance`

after each item built, allowing stateful facts to change as the sequence advances. - Build a sequence from scratch such that all Facts are satisfied. Each Fact will run
`Fact::advance`

after each item built, allowing stateful facts to change as the sequence advances. - Check that all of the constraints of all Facts are satisfied for this sequence. Each Fact will run
`Fact::advance`

after each item checked, allowing stateful facts to change as the sequence advances. - Specifies that a value should be increasing by 1 at every check/mutation
- Specifies that a value should be increasing by 1 at every check/mutation, with no context given
- Specifies an inequality constraint between two items in a tuple
- Specifies an equality constraint
- Specifies an equality constraint with no context
- Specifies a range constraint
- Specifies a range constraint
- Specifies a membership constraint
- Specifies a membership constraint
- Lifts a Fact about a subset of some data into a Fact about the superset.
- A fact which is defined based on the data to which it is applied. It maps the data into a fact to be applied.
- A version of
`mapped`

whose closure returns a Result - Specifies an inequality constraint
- Specifies an inequality constraint with no context
- A constraint which is never met
- Negates a fact
- Negates a fact, with no context given
- Combines two constraints so that either one may be satisfied
- Lifts a Fact about some
*optional*subset of data into a Fact about the superset. - Specifies an equality constraint between two items in a tuple