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.