Developing Assertables is straightforward. This page explains how to create the code for a typical Assertables macro, in three forms, using the example of the macro assert_gt.
We write each macro in three forms:
-
assert_gt_as_resultreturns aResultasOk,Err. This macro contains all the logic, all the error formatting, etc. This macro is especially useful for runtime checks, such as when you want to know success or failure, and you don't want to panic. This macro is called by the other forms below. -
assert_gtreturns successfully or does a panic. This is the typical macro that most developers will use for testing. This macro wrapsassert_gt_as_result. This macro provides two arms: one arm is for returning the error message as is, and one arm is for returning a developer's custom error message. -
debug_assert_gtreturns successfully or does a panic, when the program is running using Rust debug configuration. This macro's statements are only enabled in non-optimized builds by default. An optimized build will not execute this macro's statements unless-C debug-assertionsis passed to the compiler.
The sections below show each of the three forms, using our simplest macro group: assert_gt_as_result, assert_gt, debug_assert_gt.
The macro assert_gt_as_result returns a Result as Ok, Err.
The macro contains all the logic and all the error formatting.
The macro is called by the other forms: directly by assert_gt and indirectly by debug_assert_gt.
The macros is useful for runtime checks, such as when you want to know success or failure, and you don't want to panic.
Code:
#[macro_export]
macro_rules! assert_gt_as_result {
($a:expr, $b:expr $(,)?) => {
match ($a, $b) {
(a, b) => {
if a > b {
Ok(())
} else {
Err(
format!(
concat!(
"assertion failed: `assert_gt!(a, b)`\n",
"https://docs.rs/assertables/10.0.0/assertables/macro.assert_gt.html\n",
" left label: `{}`,\n",
" left debug: `{:?}`,\n",
" right label: `{}`,\n",
" right debug: `{:?}`"
),
stringify!($a),
a,
stringify!($b),
b
)
)
}
}
}
};
}The macro assert_gt returns successfully or panics.
The macro is the typical macro that most developers will use for testing.
The macro wraps assert_gt_as_result.
The macro provides two arms: one arm is for returning the error message as is, and one arm is for returning a developer's custom error message.
Code:
#[macro_export]
macro_rules! assert_gt {
($a:expr, $b:expr $(,)?) => {
match $crate::assert_gt_result!($a, $b) {
Ok(x) => x,
Err(err) => panic!("{}", err),
}
};
($a:expr, $b:expr, $($message:tt)+) => ({
match $crate::assert_gt!($a, $b) {
Ok(x) => x,
Err(_err) => panic!("{}", $($message)+),
}
};
}The macro debug_assert_gt return () or panics.
The macro is the typical macro that most developers will use for runtime debugging during development, and possibly also for runtime debugging during production.
The macro's statements are only enabled in non-optimized builds by default. An optimized build will not execute this macro's statements unless -C debug-assertions is passed to the compiler.
The macro wraps assert_gt.
Code:
#[macro_export]
macro_rules! debug_assert_gt {
($($arg:tt)*) => {
if cfg!(debug_assertions) {
$crate::assert_gt!($($arg)*);
}
};
}