fixin
is a basic test fixture tool for rust.
The idea is to wrap arbitrary tests in other functions (which are responsible for setup and tear down).
For example, imagine you have the test
#[test]
fn test_which_needs_some_setup() {
// ... test logic ...
}
You could write something like
#[test]
fn test_which_needs_some_setup() {
do_setup();
// ... test logic ...
do_teardown();
}
but now you have a problem: what if the test fails before you call do_teardown
?
You could try to rig your test to always call the teardown. But this will require messing with what would otherwise be very direct test logic. Tests themselves need to be as simple as possible, so this is fairly undesirable.
The simplest method I know of to address this problem is a decorator strategy.
That is where this crate comes in.
wrap
is a decorator method aimed at making test fixtures (or function decorators in general)
easier to use.
Somewhat formally, wrap
accepts an impl FnOnce(F) -> T where F: FnOnce() -> T
and produces
a test function wrapped in the supplied function.
That is a somewhat dense explanation, so an example is in order.
Imagine you have
#[test]
fn test_which_needs_setup_and_teardown() {
do_setup(some_setup_params);
// ... test logic ...
do_teardown(some_teardown_params);
}
but what you want is something
#[test]
#[with_setup_and_teardown]
fn test_which_needs_setup_and_teardown() {
// ... test logic ...
}
Then you can write
fn with_setup_and_teardown<F: UnwindSafe + FnOnce() -> T, T>(
setup_params: SetupParms,
teardown_params: TeardownParams,
) -> impl FnOnce(F) -> T {
move |f: F| {
do_setup(setup_params);
let ret = catch_unwind(f);
do_teardown(teardown_params);
ret.unwrap() // could match here as well
}
}
#[test]
#[fixin::wrap(with_setup_and_teardown(SetupParams, TeardownParams))]
fn my_test() {
// regular test logic
}
#[test]
#[fixin::wrap(with_setup_and_teardown(SetupParams, TeardownParams))]
fn my_other_test() {
// regular test logic
}