Attribute Macro rstest::fixture[][src]

#[fixture]

Define a fixture that you can use in all rstest’s test arguments. You should just mark your function as #[fixture] and then use it as a test’s argument. Fixture functions can also use other fixtures.

Let’s see a trivial example:

use rstest::*;

#[fixture]
fn twenty_one() -> i32 { 21 }

#[fixture]
fn two() -> i32 { 2 }

#[fixture]
fn injected(twenty_one: i32, two: i32) -> i32 { twenty_one * two }

#[rstest]
fn the_test(injected: i32) {
    assert_eq!(42, injected)
}

If the fixture function is an async function your fixture become an async fixture.

Default values

If you need to define argument default value you can use #[default = expression] argument’s attribute:

use rstest::*;

#[fixture]
fn injected(
    #[default = 21]
    twenty_one: i32,
    #[default = 2]
    two: i32
) -> i32 { twenty_one * two }

#[rstest]
fn the_test(injected: i32) {
    assert_eq!(42, injected)
}

The expression could be any valid rust expression, even an async block if you need.

Async

If you need you can write async fixtures to use in your async tests. Simply use async keyword for your function and the fixture become an async fixture.

use rstest::*;

#[fixture]
async fn async_fixture() -> i32 { 42 }


#[rstest]
async fn the_test(async_fixture: impl Future<Output = i32>) {
    assert_eq!(42, async_fixture.await)
}

Partial Injection

You can also partialy inject fixture dependency using #[with(v1, v2, ..)] attribute:

use rstest::*;

#[fixture]
fn base() -> i32 { 1 }

#[fixture]
fn first(base: i32) -> i32 { 1 * base }

#[fixture]
fn second(base: i32) -> i32 { 2 * base }

#[fixture]
fn injected(first: i32, #[with(3)] second: i32) -> i32 { first * second }

#[rstest]
fn the_test(injected: i32) {
    assert_eq!(-6, injected)
}

Note that injected value can be an arbitrary rust expression. #[with(v1, ..., vn)] attribute will inject v1, ..., vn expression as fixture arguments: all remaining arguments will be resolved as fixtures.

Sometimes the return type cannot be infered so you must define it: For the few times you may need to do it, you can use the #[default(type)], #[partial_n(type)] function attribute to define it:

use rstest::*;

#[fixture]
pub fn i() -> u32 {
    42
}

#[fixture]
pub fn j() -> i32 {
    -42
}

#[fixture]
#[default(impl Iterator<Item=(u32, i32)>)]
#[partial_1(impl Iterator<Item=(I,i32)>)]
pub fn fx<I, J>(i: I, j: J) -> impl Iterator<Item=(I, J)> {
    std::iter::once((i, j))
}

#[rstest]
fn resolve_by_default<I: Debug + PartialEq>(mut fx: impl Iterator<Item=I>) {
    assert_eq!((42, -42), fx.next().unwrap())
}

#[rstest]
fn resolve_partial<I: Debug + PartialEq>(#[with(42.0)] mut fx: impl Iterator<Item=I>) {
    assert_eq!((42.0, -42), fx.next().unwrap())
}

partial_i is the fixture used when you inject the first i arguments in test call.

Old compact syntax

There is also a compact form for all previous features. This will mantained for a long time but for fixture I strongly recomand to migrate your code because you’ll pay a little verbosity but get back a more readable code.

Follow the previous examples in old compact syntax.

Default

#[fixture(twenty_one=21, two=2)]
fn injected(twenty_one: i32, two: i32) -> i32 { twenty_one * two }

Partial Injection

#[fixture(second(-3))]
fn injected(first: i32, second: i32) -> i32 { first * second }

Partial Type Injection

#[fixture(::default<impl Iterator<Item=(u32, i32)>>::partial_1<impl Iterator<Item=(I,i32)>>)]
pub fn fx<I, J>(i: I, j: J) -> impl Iterator<Item=(I, J)> {
    std::iter::once((i, j))
}