This crate provides a new assertion macro assert_that!
based on matching predicates (matchers) to
* make writing asserts easier
* make reading asserts comprehendable
* easily extend the assertion framework
* provide a large list common matchers
* integrate with galvanic-test and galvanic-mock (both still in development ... stay tuned!)
* be used with your favourite test framework
The crate will be part of galvanic---a complete test framework for Rust.
galvanic-assert currently requires nightly until impl trait returns have been stabilized.
Each assertion has the form assert_that!(SOME_VALUE, MATCHES_SOMETHING);
.
To check if some value satisfies some matching predicate, e.g., less_than
, contains_in_order
, is_variant!
, ...; we can write something like the following to when operating on a single value:
```rust
extern crate galvanicassert; use galvanicassert::matchers::*;
fn expressionshouldcomputecorrectvalue { assertthat!(1+2, eq(3)); // or more wordy ... assertthat!(1+2, is(eq(3))); } ```
or assert properties of collections ... ```rust use galvanic_assert::matchers::collection::*;
fn expressionshouldcomputecorrectvalue { /// check for containment assertthat!(vec![5,1,3,4,2], containsinanyorder(vec![1,2,3,4,5])); // check for internal structure assertthat!(vec![4,3,2,1], sorteddescending()); } ```
or of variants ... ```rust enum Variants { First(i32), Second { x: i32, y: i32 }, Third }
fn shouldbethecorrectvariant { let var = Second { x: 1, y: 2 }; assertthat!(var, isvariant!(Variants::Second)); } ```
It is also possible to combine multiple matchers to create more expressive ones ... ```rust
fn expressionshouldcomputecorrectvalue { // invert the meaning of a matcher assertthat!(1+2, not(greaterthan(3))); // join several matchers conjunctively assertthat!(1+2, allof!(greaterthan(0), lessthan(5))); // join several matchers disjunctively assertthat!(1+2, anyof!(greaterthan(5), lessthan(5))); } ```
If this is not enough you can write your own matchers, either as a closure ... ```rust
fn expressionshouldcomputecorrectvalue { assertthat!(1+2, |x| { let builder = MatchResultBuilder::for("odd"); if x % 2 == 1 { builder.matched() } else { builder.failed_because("result is not odd") } }); } ```
or if it is easy enough, as an expression ... ```rust
fn expressionshouldcomputecorrectvalue {
let val = 1 + 2;
assert_that!(val % 2 == 1, otherwise "result is not odd");
}
``
If it is more complex implement the
Matcher` trait for some struct representing the state of the matcher.
Asserting positive things is good, but sometimes we expect that something goes horribly wrong ... ```rust fn pressbigred_button() { panic!("shouldn't have done that ..."); }
fn sometingshouldgowrong { assertthat!(pressbigred_button(), panics); } ```
... except when it doesn't. ```rust fn pressfaultyred_button() { return; panic!("shouldn't have done that ..."); }
fn everythingisfine { assertthat!(pressfaultyredbutton(), does not panic); } ```
Not much more to say---have a look at the documentation and the growing list of matchers.
And remember ... only tested code is happy code!
Contributions are very welcome! (Please read and agree with the license.)
The list of included matchers is far from complete.
If you encounter a useful matcher please open an issue.
Check before if there's already a boolean predicate on the type itself, e.g., like Option::is_none()
.
Those are already supported by the assertion macros and should only be included if the error message of the Matcher
is substantially better than the default one.
If something is missing or broken, please open an issue and send (if you want to) a pull request.
For pull requests be sure to include test cases to avoid regressions.
Tests for Matchers
should be added as integration tests as they test the integration with the assertion macros.
Have a look at the existing ones!