Crate Status Apache 2.0 Licensed MIT Licensed

Reuse rstest's parametrized cases

:warning: Version 0.2.0 introduce a breaking change

This crate give a way to define a tests set and apply them to every case you need to test. With rstest crate you can define a tests list but if you want to apply the same tests to another test function you must rewrite all cases or write some macros that do the job.

Both solutions have some drawbreak: - intruduce duplication - macros makes code harder to read and shift out the focus from tests core

The aim of this crate is solve this problem. rstest_resuse expose two attributes: - #[template]: to define a template - #[apply]: to apply a defined template to create tests

Here is a simple example:

``rust use rstest::rstest; use rstest_reuse::{self, *}; // Here we define the template. This define // * The test list name totwosimplecases` // * cases: here two cases

[template]

[rstest]

[case(2, 2)]

[case(4/2, 2)]

// Define a and b as cases arguments fn twosimplecases(#[case] a: u32, #[case] b: u32) {} // Here we apply the two_simple_cases template: That is expanded in // #[template] // #[rstest] // #[case(2, 2)] // #[case(4/2, 2)] // fn it_works(#[case] a: u32,#[case] b: u32) { // assert!(a == b); // }

[apply(twosimplecases)]

fn it_works(a: u32, b: u32) { assert!(a == b); } // Here we reuse the two_simple_cases template to create two // other tests

[apply(twosimplecases)]

fn it_fail(a: u32, b: u32) { assert!(a != b); } ```

If we run cargo test we have:

text Finished test [unoptimized + debuginfo] target(s) in 0.05s Running target/debug/deps/playground-8a1212f8b5eb00ce running 4 tests test it_fail::case_1 ... FAILED test it_works::case_1 ... ok test it_works::case_2 ... ok test it_fail::case_2 ... FAILED failures: ---- it_fail::case_1 stdout ---- -------------- TEST START -------------- thread 'it_fail::case_1' panicked at 'assertion failed: a != b', src/main.rs:34:5 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace ---- it_fail::case_2 stdout ---- -------------- TEST START -------------- thread 'it_fail::case_2' panicked at 'assertion failed: a != b', src/main.rs:34:5 failures: it_fail::case_1 it_fail::case_2 test result: FAILED. 2 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out error: test failed, to rerun pass '--bin playground'

Simple and neat!

Note that if the test arguments names match the template's ones you can don't repeate the arguments attributes.

Composition and Values

If you need to add some cases or values when apply a template you can leverage on composition. Here a simple example:

```rust

[template]

[rstest]

[case(2, 2)]

[case(4/2, 2)]

fn base(#[case] a: u32, #[case] b: u32) {}

// Here we add a new case and an argument in a value list:

[apply(base)]

[case(9/3, 3)]

fn it_works(a: u32, b: u32, #[values("a", "b")] t: &str) { assert!(a == b); assert!("abcd".contains(t)) } ```

run 6 tests:

running 6 tests test it_works::case_1::t_2 ... ok test it_works::case_2::t_2 ... ok test it_works::case_2::t_1 ... ok test it_works::case_3::t_2 ... ok test it_works::case_3::t_1 ... ok test it_works::case_1::t_1 ... ok

Template can also used for values and with arguments if you need:

```rust

[template]

[rstest]

fn base(#[with(42)] fix: u32, #[values(1,2,3)] v: u32) {}

[fixture]

fn fix(#[default(0)] inner: u32) -> u32 { inner }

[apply(base)]

fn useitwith_fixture(fix: u32, v: u32) { assert!(fix%v == 0); }

[apply(base)]

fn useitwithout_fixture(v: u32) { assert!(24 % v == 0); } ```

Run also 6 tests:

running 6 tests test use_it_with_fixture::v_1 ... ok test use_it_without_fixture::v_1 ... ok test use_it_with_fixture::v_3 ... ok test use_it_without_fixture::v_2 ... ok test use_it_without_fixture::v_3 ... ok test use_it_with_fixture::v_2 ... ok

Cavelets

use rstest_resuse at the top of your crate

You should add use rstest_resuse at the top of your crate:

```rust

[cfg(test)]

use rstest_reuse; ```

This is due rstest_reuse::template define a macro that need to call a rstest_resuse's macro. I hope to remove this in the future but for now we should live with it.

Note that

rust use rstest_reuse::*; is not enougth: this statment doesn't include rstest_reuse but just its public items.

#[export] Attribute

:warning: Version 0.2.0 introduce a breaking change

If you want to export your template at the root of your crate you should annotate it by #[export] attribute. Use #[export] attribute also if you need to use the template from another crate.

This was the default behaviour in the 0.1.x versions.

Example: note that we don't use #[macro_use] attribute.

```rust mod inner { mod sub { use rstestreuse::*; #[template] #[export] #[rstest(a, b, case(2, 2), case(4/2, 2), ) ] fn twosimplecases(a: u32, b: u32) {} } } use rstestreuse::; use rstest::;

[apply(twosimplecases)]

fn it_works(a: u32, b: u32) { assert!(a == b); } ```

Disclamer

This crate is in a development stage. I don't know if I'll include it in rstest or change some syntax in the future.

I did't test it in a lot of cases: if you have some cases where it doesn't works file a ticket on rstest

License

Licensed under either of