diff --git a/CHANGELOG.md b/CHANGELOG.md index d0a7053..91c349b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,9 @@ ### Add - `#![no_std]` support: now you can use `rstest` also in `no_std` lib -(see [#282](https://github.com/la10736/rstest/issues/282) thanks to @rnbguy) + (see [#282](https://github.com/la10736/rstest/issues/282) thanks to @rnbguy) +- `#[context]` to have test function name and other useful thighs on + the tip of your fingers (see [#177](https://github.com/la10736/rstest/issues/177)) ### Fixed diff --git a/README.md b/README.md index 71affd8..bfb0a2b 100644 --- a/README.md +++ b/README.md @@ -133,7 +133,6 @@ use rstest::rstest; #[rstest] #[case(2, 2)] #[cfg_attr(feature = "frac", case(4/2, 2))] -#[case(4/2, 2)] fn it_works(#[case] a: u32, #[case] b: u32) { assert!(a == b); } @@ -264,10 +263,24 @@ base directory. That directory MUST exist, and will be used as the root for the files, as well as to resolve the relative path when creating the test name. Similar to the `files` attribute, you can use `${ENV_VAR_NAME}` in the `base_dir`. -### Default timeout +### Use `#[once]` Fixture -You can set a default timeout for test using the `RSTEST_TIMEOUT` environment variable. -The value is in seconds and is evaluated on test compile time. +If you need to a fixture that should be initialized just once for all tests +you can use `#[once]` attribute. `rstest` call your fixture function just once and +return a reference to your function result to all your tests: + +```rust +#[fixture] +#[once] +fn once_fixture() -> i32 { 42 } + +#[rstest] +fn single(once_fixture: &i32) { + // All tests that use once_fixture will share the same reference to once_fixture() + // function result. + assert_eq!(&42, once_fixture) +} +``` ### Test `#[timeout()]` @@ -319,6 +332,11 @@ async fn group_one_timeout_override(#[case] delay: Duration, #[case] expected: u If you want to use `timeout` for `async` test you need to use `async-timeout` feature (enabled by default). +### Default timeout + +You can set a default timeout for test using the `RSTEST_TIMEOUT` environment variable. +The value is in seconds and is evaluated on test compile time. + ### Inject Test Attribute If you would like to use another `test` attribute for your test you can simply @@ -342,22 +360,23 @@ async fn my_async_test(#[case] a: u32, #[case] Just the attributes that ends with `test` (last path segment) can be injected. -### Use `#[once]` Fixture +## Test `Context` object -If you need to a fixture that should be initialized just once for all tests -you can use `#[once]` attribute. `rstest` call your fixture function just once and -return a reference to your function result to all your tests: +You can have a [`Context`] object for your test just by annotate an argument by `#[context]` attribute. +This object contains some useful information both to implement simple logics and debugging stuff. ```rust -#[fixture] -#[once] -fn once_fixture() -> i32 { 42 } +use rstest::{rstest, Context}; #[rstest] -fn single(once_fixture: &i32) { - // All tests that use once_fixture will share the same reference to once_fixture() - // function result. - assert_eq!(&42, once_fixture) +#[case::a_description(42)] +fn my_test(#[context] ctx: Context, #[case] _c: u32) { + assert_eq!("my_test", ctx.name); + assert_eq!(Some("a_description"), ctx.description); + assert_eq!(Some(0), ctx.case); + + std::thread::sleep(std::time::Duration::from_millis(100)); + assert!(ctx.start.elapsed() >= std::time::Duration::from_millis(100)); } ``` diff --git a/rstest/src/context.rs b/rstest/src/context.rs index c458cf5..bbc7949 100644 --- a/rstest/src/context.rs +++ b/rstest/src/context.rs @@ -3,17 +3,18 @@ pub struct Context { /// The complete module test path pub module: &'static str, - /// The complete test name + /// The test function name pub name: &'static str, - /// The optional test description + /// The test description if present pub description: Option<&'static str>, - /// The optional case number + /// The cardinal case number if it's a test case pub case: Option, /// Start time pub start: std::time::Instant, } impl Context { + /// Create a new test context. This function set also the start time to the current time. pub fn new( module: &'static str, name: &'static str, diff --git a/rstest/src/lib.rs b/rstest/src/lib.rs index 2306a91..3a38f6a 100644 --- a/rstest/src/lib.rs +++ b/rstest/src/lib.rs @@ -607,6 +607,25 @@ pub use rstest_macros::fixture; /// - Generate [parametrized test cases](#test-parametrized-cases) /// - Generate tests for each combination of [value lists](#values-lists) /// +/// Additional Attributes: +/// +/// - Function Attributes: +/// - [`#[case]`](#test-parametrized-cases) define a parametrized test case +/// - [`#[awt]`](#async) await all your future test function's inputs +/// - [`#[timeout(...)]`](#test-timeout) define a test timeout +/// - [`#[trace]`](#trace-input-arguments) tracing input arguments +/// - Arguments Attributes: +/// - [`#[case]`](#test-parametrized-cases) define an argument parametrized by test cases +/// - [`#[values(...)]`](#values-lists) define an argument that can be a list of values +/// - [`#[files(...)]`-`#[exclude(...)]`-`#[base_dir = ... ]`](#files-path-as-input-arguments) +/// define an argument that can be a list of path based on a glob pattern +/// - [`#[from(...)]`-`#[with(...)]`](#injecting-fixtures) handling injected fixture +/// - [`#[future]`](#async) implement future boilerplate argument +/// - [`#[context]`](#test-context-object) Some metadata test information +/// - [`#[by_ref]`](#local-lifetime-and-by_ref-attribute) define a local lifetime +/// - [`#[ignore]`](#ignoring-arguments) ignore an argument used by a custom test function +/// - [`#[notrace]`](#trace-input-arguments) disable trace +/// /// ## Injecting Fixtures /// /// The simplest case is write a test that can be injected with @@ -760,7 +779,6 @@ pub use rstest_macros::fixture; /// #[rstest] /// #[case(2, 2)] /// #[cfg_attr(feature = "frac", case(4/2, 2))] -/// #[case(4/2, 2)] /// fn it_works(#[case] a: u32, #[case] b: u32) { /// assert!(a == b); /// } @@ -942,7 +960,7 @@ pub use rstest_macros::fixture; /// /// ## Destructuring inputs /// -/// Both paramtrized case and values can be destructured: +/// Both parametrized case and values can be destructured: /// /// ``` /// # use rstest::*; @@ -1112,11 +1130,6 @@ pub use rstest_macros::fixture; /// } /// ``` /// -/// ### Default timeout -/// -/// You can set a default timeout for test using the `RSTEST_TIMEOUT` environment variable. -/// The value is in seconds and is evaluated on test compile time./// -/// /// ### Test `#[timeout()]` /// /// You can define an execution timeout for your tests with `#[timeout()]` attribute. Timeout @@ -1173,6 +1186,11 @@ pub use rstest_macros::fixture; /// If you want to use `timeout` for `async` test you need to use `async-timeout` /// feature (enabled by default). /// +/// ### Default timeout +/// +/// You can set a default timeout for test using the `RSTEST_TIMEOUT` environment variable. +/// The value is in seconds and is evaluated on test compile time. +/// /// ## Inject Test Attribute /// /// If you would like to use another `test` attribute for your test you can simply @@ -1200,6 +1218,27 @@ pub use rstest_macros::fixture; /// This can lead to compile errors when rstest is not able to resolve the additional arguments. /// To avoid this, see [Ignoring Arguments](attr.rstest.html#ignoring-arguments). /// +/// ## Test `Context` object +/// +/// You can have a [`Context`] object for your test just by annotate an argument by `#[context]` attribute. +/// This object contains some useful information both to implement simple logics and debugging stuff. +/// +/// ``` +/// use rstest::{rstest, Context}; +/// +/// #[rstest] +/// #[case::a_description(42)] +/// fn my_test(#[context] ctx: Context, #[case] _c: u32) { +/// assert_eq!("my_test", ctx.name); +/// assert_eq!(Some("a_description"), ctx.description); +/// assert_eq!(Some(0), ctx.case); +/// +/// std::thread::sleep(std::time::Duration::from_millis(100)); +/// assert!(ctx.start.elapsed() >= std::time::Duration::from_millis(100)); +/// } +/// +/// ``` +/// /// ## Local lifetime and `#[by_ref]` attribute /// /// In some cases you may want to use a local lifetime for some arguments of your test.