From d35ade2521ed532ad414adb00c68ff14bd855473 Mon Sep 17 00:00:00 2001 From: la10736 Date: Sun, 4 Aug 2024 18:26:20 +0200 Subject: [PATCH] Docs and make clippy happy --- CHANGELOG.md | 2 + rstest/src/lib.rs | 54 ++++++++++++++++++++++ rstest_macros/src/error.rs | 2 +- rstest_macros/src/parse/arguments.rs | 2 +- rstest_macros/src/parse/mod.rs | 2 +- rstest_macros/src/parse/rstest/files.rs | 6 +-- rstest_macros/src/render/apply_argumets.rs | 2 +- rstest_macros/src/render/fixture.rs | 2 - rstest_macros/src/render/inject.rs | 2 +- rstest_reuse/tests/acceptance.rs | 4 +- 10 files changed, 63 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6380357..f9f2ad4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ### Changed +- Now it's possible destructuring input values both for cases, values and fixtures. See [#231](https://github.com/la10736/rstest/issues/231) for details + ### Add - Implemented `#[ignore]` attribute to ignore test parameters during fixtures resolution/injection. See [#228](https://github.com/la10736/rstest/issues/228) for details diff --git a/rstest/src/lib.rs b/rstest/src/lib.rs index e84563d..d33b41f 100644 --- a/rstest/src/lib.rs +++ b/rstest/src/lib.rs @@ -354,6 +354,22 @@ pub mod timeout; /// shorter name for argument that represent it in your fixture or test. You can rename the fixture /// using `#[from(short_name)]` attribute like following example: /// +/// ## Destructuring +/// +/// It's possible to destructure the fixture type but, in this case, your're forced to use renaming syntax +/// because it's not possible to guess the fixture name from this syntax: +/// +/// ``` +/// use rstest::*; +/// #[fixture] +/// fn two_values() -> (u32, u32) { (42, 24) } +/// +/// #[rstest] +/// fn the_test(#[from(two_values)] (first, _): (u32, u32)) { +/// assert_eq!(42, first) +/// } +/// ``` +/// /// ``` /// use rstest::*; /// @@ -568,6 +584,9 @@ pub use rstest_macros::fixture; /// - return results /// - marked by `#[should_panic]` attribute /// +/// In the function signature, where you define your tests inputs, you can also destructuring +/// the values like any other rust function. +/// /// If the test function is an [`async` function](#async) `rstest` will run all tests as `async` /// tests. You can use it just with `async-std` and you should include `attributes` in /// `async-std`'s features. @@ -624,6 +643,20 @@ pub use rstest_macros::fixture; /// } /// ``` /// +/// The use of `#[from(...)]` attribute is mandatory if you need to destructure the value: +/// +/// ``` +/// use rstest::*; +/// +/// #[fixture] +/// fn tuple() -> (u32, f32) { (42, 42.0) } +/// +/// #[rstest] +/// fn the_test(#[from(tuple)] (u, _): (u32, f32)) { +/// assert_eq!(42, u) +/// } +/// ``` +/// /// Sometimes is useful to have some parameters in your fixtures but your test would /// override the fixture's default values in some cases. Like in /// [fixture partial injection](attr.fixture.html#partial-injection) you use `#[with]` @@ -897,6 +930,27 @@ pub use rstest_macros::fixture; /// } /// ``` /// +/// ## Destructuring inputs +/// +/// Both paramtrized case and values can be destructured: +/// +/// ``` +/// # use rstest::*; +/// struct S { +/// first: u32, +/// second: u32, +/// } +/// +/// struct T(i32); +/// +/// #[rstest] +/// #[case(S{first: 21, second: 42})] +/// fn some_test(#[case] S{first, second} : S, #[values(T(-1), T(1))] T(t): T) { +/// assert_eq!(1, t * t); +/// assert_eq!(2 * first, second); +/// } +/// ``` +/// /// ## Files path as input arguments /// /// If you need to create a test for each file in a given location you can use diff --git a/rstest_macros/src/error.rs b/rstest_macros/src/error.rs index 5de23d3..78db9f9 100644 --- a/rstest_macros/src/error.rs +++ b/rstest_macros/src/error.rs @@ -14,7 +14,7 @@ use crate::refident::{MaybeIdent, MaybePat}; use super::utils::fn_args_has_pat; pub mod messages { - pub const DESTRUCT_WITHOUT_FROM : &'static str = "To destruct a fixture you should provide a path to resolve it by '#[from(...)]' attribute."; + pub const DESTRUCT_WITHOUT_FROM : &str = "To destruct a fixture you should provide a path to resolve it by '#[from(...)]' attribute."; pub fn use_more_than_once(name: &str) -> String { format!("You cannot use '{name}' attribute more than once for the same argument") } diff --git a/rstest_macros/src/parse/arguments.rs b/rstest_macros/src/parse/arguments.rs index dd9b0fb..ab2b94b 100644 --- a/rstest_macros/src/parse/arguments.rs +++ b/rstest_macros/src/parse/arguments.rs @@ -85,7 +85,7 @@ impl Args { fn get(&self, pat: &Pat) -> Option<&ArgumentInfo> { self.args .get(pat) - .or_else(|| self.args.get(&pat_invert_mutability(&pat))) + .or_else(|| self.args.get(&pat_invert_mutability(pat))) } fn entry(&mut self, pat: Pat) -> std::collections::hash_map::Entry { diff --git a/rstest_macros/src/parse/mod.rs b/rstest_macros/src/parse/mod.rs index 5fddb84..3115edf 100644 --- a/rstest_macros/src/parse/mod.rs +++ b/rstest_macros/src/parse/mod.rs @@ -278,7 +278,7 @@ pub(crate) fn extract_argument_attrs<'a, B: 'a + std::fmt::Debug>( arg.attrs = remain; // Parse attrs - Box::new(extracted.into_iter().map(move |attr| build(attr))) + Box::new(extracted.into_iter().map(build)) } else { Box::new(std::iter::empty()) } diff --git a/rstest_macros/src/parse/rstest/files.rs b/rstest_macros/src/parse/rstest/files.rs index 35c259c..c4597cb 100644 --- a/rstest_macros/src/parse/rstest/files.rs +++ b/rstest_macros/src/parse/rstest/files.rs @@ -180,11 +180,7 @@ impl ValueFilesExtractor { } fn extract_exclude(&mut self, node: &mut FnArg) -> Vec { - self.extract_argument_attrs( - node, - |a| attr_is(a, "exclude"), - |attr| Exclude::try_from(attr), - ) + self.extract_argument_attrs(node, |a| attr_is(a, "exclude"), Exclude::try_from) } fn extract_include_dot_files(&mut self, node: &mut FnArg) -> Vec { diff --git a/rstest_macros/src/render/apply_argumets.rs b/rstest_macros/src/render/apply_argumets.rs index e8fa8ae..ff1f754 100644 --- a/rstest_macros/src/render/apply_argumets.rs +++ b/rstest_macros/src/render/apply_argumets.rs @@ -85,7 +85,7 @@ impl ApplyArguments for ItemFn { let rebound_awaited_args = args .iter() .filter_map(MaybePat::maybe_pat) - .filter(|p| arguments.is_future_await(&p)) + .filter(|p| arguments.is_future_await(p)) .filter_map(MaybePatIdent::maybe_patident) .map(|p| { let a = &p.ident; diff --git a/rstest_macros/src/render/fixture.rs b/rstest_macros/src/render/fixture.rs index d0cfd08..206d002 100644 --- a/rstest_macros/src/render/fixture.rs +++ b/rstest_macros/src/render/fixture.rs @@ -139,8 +139,6 @@ fn render_partial_impl( let generics = generics_clean_up(generics, args.iter().take(n), &output); let where_clause = &generics.where_clause; - let asyncness = asyncness; - let genercs_idents = generics .type_params() .map(|tp| &tp.ident) diff --git a/rstest_macros/src/render/inject.rs b/rstest_macros/src/render/inject.rs index ccd20e8..7d5a050 100644 --- a/rstest_macros/src/render/inject.rs +++ b/rstest_macros/src/render/inject.rs @@ -67,7 +67,7 @@ where }) } - fn fixture_name<'a>(&self, ident: &'a Pat) -> Ident { + fn fixture_name(&self, ident: &Pat) -> Ident { let ident = ident .maybe_ident() .cloned() diff --git a/rstest_reuse/tests/acceptance.rs b/rstest_reuse/tests/acceptance.rs index 66ff656..c204b50 100644 --- a/rstest_reuse/tests/acceptance.rs +++ b/rstest_reuse/tests/acceptance.rs @@ -187,9 +187,7 @@ fn should_export_main_root() { fn rstest_reuse_not_in_crate_root() { let (output, _) = run_test("rstest_reuse_not_in_crate_root.rs"); - TestResults::new() - .ok("test::case_1") - .assert(output); + TestResults::new().ok("test::case_1").assert(output); } lazy_static! {