I am implementing a data structure with an inner invariant that I want to cover by tests. This invariant is a part of the data structure; thus, if implemented properly, it could never be violated by any sequence of actions of a data structure user, but I obviously still want it to be tested.
Currently, I simply use debug_assert!
to test invariants, and my code looks like this:
fn test_invariant(&self) -> bool {
// some computations
}
fn some_algorithm(&self) {
// some code
debug_assert!(self.test_invariant());
// more code
}
However, since test_invariant
is somewhat computationally expensive and should never trigger in user's code, I want the assert to be active only in my own tests. Also, the invariant is a part of the algorithm, and so the assert could not be easily moved to unit tests (you can think of it as testing the heap invariant while implementing an in-place version of heapsort). Is it possible to do it in Rust?
As written, the test_invariant
method will only be invoked in debug builds. That is, the expression in the argument will not be evaluated at all in non-debug builds, which is different from the behaviour that you'd see if debug_assert
was a function rather than a macro. This is usually what people want, since production binaries will be a release build and tests use debug.
If you are concerned about very slow code making it impractical for you to run debug builds, you could make your own macro that is conditionally defined, depending on if you are in tests or not:
macro_rules! test_assert {
($($tt: tt)*) => {
#[cfg(test)]
assert!($($tt)*)
}
}
The test_assert!
macro will behave just like debug_assert!
except will only do anything in tests.
Usually, though, it's much clearer if test assertions are done explicitly in tests where possible.