diff --git a/CHANGELOG.md b/CHANGELOG.md index a272f94f..e5dd4fe5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ ### Add - Implemented `#[by_ref]` attribute to take get a local lifetime for test arguments. -See [#241](https://github.com/la10736/rstest/issues/241) for more details. Thanks to +See [#241](https://github.com/la10736/rstest/issues/241) for more details. Thanks to @narpfel for suggesting it and useful discussions. ### Fixed @@ -16,6 +16,8 @@ See [#241](https://github.com/la10736/rstest/issues/241) for more details. Thank [#241](https://github.com/la10736/rstest/issues/241) for more details. - [`PathBuf`](https://doc.rust-lang.org/std/path/struct.PathBuf.html) does no longer need to be in scope when using `#[files]` (see [#242](https://github.com/la10736/rstest/pull/242)) +- `#[from(now::accept::also::path::for::fixture)]` See [#246](https://github.com/la10736/rstest/issues/246) +for more details ## [0.19.0] 2024/4/9 diff --git a/rstest/tests/resources/fixture/rename.rs b/rstest/tests/resources/fixture/rename.rs index c3994908..ec77809a 100644 --- a/rstest/tests/resources/fixture/rename.rs +++ b/rstest/tests/resources/fixture/rename.rs @@ -5,6 +5,15 @@ fn very_long_and_boring_name(#[default(42)] inject: u32) -> u32 { inject } +mod sub_module { + use super::*; + + #[fixture] + pub fn mod_fixture() -> u32 { + 42 + } +} + #[fixture(very_long_and_boring_name as foo)] fn compact(foo: u32) -> u32 { foo @@ -15,11 +24,21 @@ fn compact_injected(foo: u32) -> u32 { foo } +#[fixture(sub_module::mod_fixture as foo)] +fn compact_from_mod(foo: u32) -> u32 { + foo +} + #[fixture] fn attribute(#[from(very_long_and_boring_name)] foo: u32) -> u32 { foo } +#[fixture] +fn attribute_mod(#[from(sub_module::mod_fixture)] foo: u32) -> u32 { + foo +} + #[fixture] fn attribute_injected( #[from(very_long_and_boring_name)] @@ -30,7 +49,16 @@ fn attribute_injected( } #[rstest] -fn test(compact: u32, attribute: u32, compact_injected: u32, attribute_injected: u32) { +fn test( + compact: u32, + attribute: u32, + attribute_mod: u32, + compact_from_mod: u32, + compact_injected: u32, + attribute_injected: u32, +) { assert_eq!(compact, attribute); + assert_eq!(attribute, attribute_mod); + assert_eq!(attribute_mod, compact_from_mod); assert_eq!(compact_injected, attribute_injected); } diff --git a/rstest/tests/resources/rstest/rename.rs b/rstest/tests/resources/rstest/rename.rs index ebd442d7..77e7d9eb 100644 --- a/rstest/tests/resources/rstest/rename.rs +++ b/rstest/tests/resources/rstest/rename.rs @@ -5,11 +5,25 @@ fn very_long_and_boring_name(#[default(42)] inject: u32) -> u32 { inject } +mod sub_module { + use super::*; + + #[fixture] + pub fn mod_fixture() -> u32 { + 42 + } +} + #[rstest(very_long_and_boring_name as foo)] fn compact(foo: u32) { assert!(42 == foo); } +#[rstest(sub_module::mod_fixture as foo)] +fn compact_mod(foo: u32) { + assert!(42 == foo); +} + #[rstest(very_long_and_boring_name(21) as foo)] fn compact_injected(foo: u32) { assert!(21 == foo); @@ -20,6 +34,11 @@ fn attribute(#[from(very_long_and_boring_name)] foo: u32) { assert!(42 == foo); } +#[rstest] +fn attribute_mod(#[from(sub_module::mod_fixture)] foo: u32) { + assert!(42 == foo); +} + #[rstest] fn attribute_injected( #[from(very_long_and_boring_name)] diff --git a/rstest/tests/rstest/mod.rs b/rstest/tests/rstest/mod.rs index 952984ae..086a9923 100644 --- a/rstest/tests/rstest/mod.rs +++ b/rstest/tests/rstest/mod.rs @@ -979,8 +979,10 @@ fn rename() { TestResults::new() .ok("compact") + .ok("compact_mod") .ok("compact_injected") .ok("attribute") + .ok("attribute_mod") .ok("attribute_injected") .assert(output); } diff --git a/rstest_macros/Cargo.toml b/rstest_macros/Cargo.toml index 8b2bdeb6..9ad12f4c 100644 --- a/rstest_macros/Cargo.toml +++ b/rstest_macros/Cargo.toml @@ -42,7 +42,7 @@ actix-rt = "2.7.0" async-std = { version = "1.12.0", features = ["attributes"] } maplit = "1.0.2" pretty_assertions = "1.2.1" -rstest = { version = "0.19.0", default-features = false } +rstest = { path = "../rstest", default-features = false } rstest_reuse = { path = "../rstest_reuse" } rstest_test = { path = "../rstest_test" } diff --git a/rstest_macros/src/lib.rs b/rstest_macros/src/lib.rs index f9f45286..9f18b639 100644 --- a/rstest_macros/src/lib.rs +++ b/rstest_macros/src/lib.rs @@ -136,6 +136,23 @@ use quote::ToTokens; /// assert_eq!(42, short) /// } /// ``` +/// +/// This feature can also be useful when you don't want to declare the `use` of a fixture or simple +/// use the fixture's path: +/// +/// ``` +/// use rstest::*; +/// +/// # mod magic_numbers { +/// # use rstest::*; +/// # #[fixture] +/// # pub fn fortytwo() -> i32 { 42 } +/// # } +/// #[rstest] +/// fn the_test(#[from(magic_numbers::fortytwo)] x: i32) { +/// assert_eq!(42, x) +/// } +/// ``` /// /// # `#[once]` Fixture /// diff --git a/rstest_macros/src/parse/fixture.rs b/rstest_macros/src/parse/fixture.rs index a5d6f0ec..b79183a8 100644 --- a/rstest_macros/src/parse/fixture.rs +++ b/rstest_macros/src/parse/fixture.rs @@ -448,6 +448,8 @@ mod extend { fn test_fn( #[from(long_fixture_name)] #[with(42, "other")] short: u32, + #[from(sub_module::fix)] + f: u32, #[from(simple)] s: &str, no_change: i32) { @@ -460,6 +462,7 @@ mod extend { fixture("short", &["42", r#""other""#]) .with_resolve("long_fixture_name") .into(), + fixture("f", &[]).with_resolve("sub_module::fix").into(), fixture("s", &[]).with_resolve("simple").into(), ] .into(), diff --git a/rstest_macros/src/parse/mod.rs b/rstest_macros/src/parse/mod.rs index d98f3a87..f009c061 100644 --- a/rstest_macros/src/parse/mod.rs +++ b/rstest_macros/src/parse/mod.rs @@ -137,12 +137,12 @@ impl Parse for Positional { #[derive(PartialEq, Debug, Clone)] pub(crate) struct Fixture { pub(crate) name: Ident, - pub(crate) resolve: Option, + pub(crate) resolve: Option, pub(crate) positional: Positional, } impl Fixture { - pub(crate) fn new(name: Ident, resolve: Option, positional: Positional) -> Self { + pub(crate) fn new(name: Ident, resolve: Option, positional: Positional) -> Self { Self { name, resolve, @@ -153,7 +153,7 @@ impl Fixture { impl Parse for Fixture { fn parse(input: ParseStream) -> syn::Result { - let resolve = input.parse()?; + let resolve: syn::Path = input.parse()?; if input.peek(Paren) || input.peek(Token![as]) { let positional = if input.peek(Paren) { let content; @@ -167,7 +167,13 @@ impl Parse for Fixture { let _: Token![as] = input.parse()?; Ok(Self::new(input.parse()?, Some(resolve), positional)) } else { - Ok(Self::new(resolve, None, positional)) + let name = resolve.get_ident().ok_or_else(|| { + syn::Error::new_spanned( + resolve.to_token_stream(), + format!("Should be an ident"), + ) + })?; + Ok(Self::new(name.clone(), None, positional)) } } else { Err(syn::Error::new( diff --git a/rstest_macros/src/parse/rstest.rs b/rstest_macros/src/parse/rstest.rs index 13a87565..911d9e7e 100644 --- a/rstest_macros/src/parse/rstest.rs +++ b/rstest_macros/src/parse/rstest.rs @@ -397,7 +397,7 @@ mod test { #[test] fn rename() { let data = parse_rstest( - r#"long_fixture_name(42, "other") as short, simple as s, no_change()"#, + r#"long_fixture_name(42, "other") as short, sub_module::fix as f, simple as s, no_change()"#, ); let expected = RsTestInfo { @@ -405,6 +405,7 @@ mod test { fixture("short", &["42", r#""other""#]) .with_resolve("long_fixture_name") .into(), + fixture("f", &[]).with_resolve("sub_module::fix").into(), fixture("s", &[]).with_resolve("simple").into(), fixture("no_change", &[]).into(), ] @@ -423,6 +424,8 @@ mod test { #[with(42, "other")] short: u32, #[from(simple)] s: &str, + #[from(sub_module::fix)] + f: u32, no_change: i32) { } "# @@ -434,6 +437,7 @@ mod test { .with_resolve("long_fixture_name") .into(), fixture("s", &[]).with_resolve("simple").into(), + fixture("f", &[]).with_resolve("sub_module::fix").into(), ] .into(), ..Default::default() diff --git a/rstest_macros/src/resolver.rs b/rstest_macros/src/resolver.rs index 51110501..e1d9c879 100644 --- a/rstest_macros/src/resolver.rs +++ b/rstest_macros/src/resolver.rs @@ -22,7 +22,10 @@ pub(crate) mod fixtures { } fn extract_resolve_expression(fixture: &Fixture) -> syn::Expr { - let resolve = fixture.resolve.as_ref().unwrap_or(&fixture.name); + let resolve = fixture + .resolve + .clone() + .unwrap_or_else(|| fixture.name.clone().into()); let positional = &fixture.positional.0; let f_name = match positional.len() { 0 => format_ident!("default"), @@ -53,13 +56,17 @@ pub(crate) mod fixtures { #[case(&[], "default()")] #[case(&["my_expression"], "partial_1(my_expression)")] #[case(&["first", "other"], "partial_2(first, other)")] - fn resolve_by_use_the_resolve_field(#[case] args: &[&str], #[case] expected: &str) { - let data = vec![fixture("pippo", args).with_resolve("pluto")]; + fn resolve_by_use_the_resolve_field( + #[case] args: &[&str], + #[case] expected: &str, + #[values("pluto", "minnie::pluto")] resolver_path: &str, + ) { + let data = vec![fixture("pippo", args).with_resolve(resolver_path)]; let resolver = get(data.iter()); let resolved = resolver.resolve(&ident("pippo")).unwrap().into_owned(); - assert_eq!(resolved, format!("pluto::{}", expected).ast()); + assert_eq!(resolved, format!("{}::{}", resolver_path, expected).ast()); } } } diff --git a/rstest_macros/src/test.rs b/rstest_macros/src/test.rs index 54eb2aae..22233254 100644 --- a/rstest_macros/src/test.rs +++ b/rstest_macros/src/test.rs @@ -115,6 +115,10 @@ pub(crate) fn ident(s: impl AsRef) -> Ident { s.as_ref().ast() } +pub(crate) fn path(s: impl AsRef) -> syn::Path { + s.as_ref().ast() +} + pub(crate) fn expr(s: impl AsRef) -> syn::Expr { s.as_ref().ast() } @@ -218,8 +222,8 @@ impl RsTestInfo { } impl Fixture { - pub fn with_resolve(mut self, resolve_ident: &str) -> Self { - self.resolve = Some(ident(resolve_ident)); + pub fn with_resolve(mut self, resolve_path: &str) -> Self { + self.resolve = Some(path(resolve_path)); self } }