Attribute Macro assert2ify::assert2ify[][src]

#[assert2ify]
Expand description

Annotate your functions (usually test cases) with this attribute and have it replace the assertions the function with the more powerful assertions from the assert2 crate.

Usage

Stick this attribute above any function in which you want the assertions replaced by the assertions from the assert2 crate. This is primarily useful for functions that are already annotated #[test], but it is possible to use with any function. See below for examples what exactly is replaced and how to use the macro

Arguments

check

The attribute can be used as #[assert2ify] without arguments, in which case it will replace assertions with assertions. If you want to replace assertions with the check! macro from the assert2 crate, use this attribute as #[assert2ify(check)]. In contrast to assertions, the check! macro only fails at the end of the test. This is useful if you want to see every failing assertion inside a test inside a single pass.

Caveat: assert!(matches!(...)) expressions will still be replaced by assertions because there is no let_check! in assert2 as it would not make sense.

crate = …

In case you felt the need to rename this crate in your cargo toml, the compiler will get confused and through an error. You can help the compiler by giving the attribute another argument in the form crate = new_crate_name. The arguments can be combined, e.g. #[assert2ify(check, crate = new_name)]. However, most of the time the crate = ... argument should not be necessary.

Which Assertions are Replaced

Simple Assertions

The attribute replaces assertions assert!, assert_eq!, assert_ne! by the corresponding assertions from the assert2 crate. This means that this test

#[test]
#[assert2ify]
fn my_test() {
    /*...*/
    assert!(my_vector.len()<20);
    assert_eq!(my_number,1234);
    assert_ne!(my_other_number, 2);
}

now behaves as if you had written it like this:

#[test]
fn my_test() {
    /*...*/
    assert2::assert!(my_vector.len()<20);
    assert2::assert!(my_number == 1234);
    assert2::assert!(my_other_number != 2);
}

assert!(matches!(...)) Expressions

These statements are e.g. used when pattern matching on Ok or Err variants in unit tests. Unfortunately they are pretty useless, because it would be nice to see not only that the match failed but what the type of the matched expression actually was. This is where let_assert of the assert2 crate shines. So if we want to test the result of some function foo like so

fn foo(input : i32) -> Result<i32,String> {
    //[...] some calculation
}
assert!(matches!(foo(-1),Err(s) if s.contains("negative value")));

then the corresponding assertion will be replaced by

assert2::let_assert!(Err(s) = foo(-1));
assert2::assert!(s.contains("negative value"));

We have to make this two assertions because as of yet, let_assert! does not support additional if statements. This will give you infinitely more helpful messages in case of panics.

Additional Arguments to the Assertions

A format string and all addtional variadic arguments to the assertions are handled as you would expect and will produce additional info output in case of panics. So an assertion assert!(j>5,"wrong number of messages") will be replaced by an assertion that also carries the additional info.

Limitations and Caveats

The crate traverses the syntax tree given by the contents of the function and replaces the occurrences of standard library assertions with the assertions of the assert2 crate. For most of the uses cases this will be fine, since assertions inside loops, closures, if-statements, etc. will be replaced

Assertions in Nested Code

However, there are some edge cases where replacing will not occur. In these cases the standard library assertions will be left untouched and the test will behave as it did previously.

Assertions Inside Assertions

Assertions inside assertions are not replaced. Only the outer assertion will be replaced while the other one is left as it was. I personally think that assertions inside assertions indicate a flawed test design and probably won’t be working to fix this issue.

Assertions Inside Macros

Assertions inside macros invocations (and definitions) are only replaced if the tokens inside the macros can be parsed as an expression. This does not cover all possible cases and I will work to change this in future versions of this crate.