1 stable release
new 1.0.0 | May 2, 2024 |
---|
#661 in Testing
26 downloads per month
Used in tested-fixture
7KB
111 lines
tested-fixture
Attribute macro for creating fixtures from tests
Description
Sometimes a series of tests are progressive/incremental; One test is targetted at verifying Step 1 works as expected, while another is focused on ensuring Step 2 functions correctly. Common advice is to duplicate all the work of Step 1 into Step 2's test, or to combine the tests into one large test. However the former approach can significantly slow down tests, while the latter can lead to large and unruly testing functions which are difficult to maintain.
This crate takes a different approach by allowing a test to return a
fixture which can be used in subsequent tests, all through the use of a
single attribute macro tested_fixture
.
Usage
When writing tests for code like:
struct Foo {
// ...
}
impl Foo {
fn step_1() -> Self {
Foo {
// Complicated setup...
}
}
fn step_2(&self) {
// Complicated execution...
}
}
An duplicated test setup would look something like
#[test]
fn step_1() {
let foo = Foo::step_1();
// Complicated assertions verify step 1...
}
#[test]
fn step_2() {
let foo = Foo::step_1();
// (Some?) Complicated assertions verify step 1...
foo.step_2();
// Complicated assertions verify step 2...
}
As you can see, with a lot of steps, this can quickly get out of hand. To
clean it up is straightforward by switching step_1
to use the
tested_fixture
attribute instead of the normal test
.
// Save the fixture in a static variable called `STEP_1`
#[tested_fixture::tested_fixture(STEP_1)]
fn step_1() -> Foo {
let foo = Foo::step_1();
// Complicated assertions verify step 1...
foo
}
#[test]
fn step_2() {
STEP_1.step_2();
// Complicated assertions verify step 2...
}
In the case where only step_2
is run, STEP_1
will be initialized on
first access. Since the order of tests is not guaranteed, this actually can
occur even if both tests are run. But since results are cached, the
step_1
test should still reproduce the same result regardless of if it is
the first access or not.
Advanced usage
The tested_fixture
attribute supports attributes and a visibility level
prefixing the identifier, as well as an optional : type
suffix. This
optional suffix can be used on tests returning a Result
to specify that
only Ok
return values should be captured. For example:
#[tested_fixture::tested_fixture(pub(crate) STEP_1: Foo)]
fn step_1() -> Result<Foo, &'static str> {
// ...
}
Limitations
Ordinary test are able to return anything which implements
std::process::Termination
, which unlimited nestings of Result
s. While
this crate does support returning nested Result
wrappings, it only does
so up to a fixed depth. Additionally it does not support returning any other
types of Termination
Right now this crate does not support async tests.
License: MIT
Dependencies
~1.4–2MB
~42K SLoC