Skip to content

Commit f96b351

Browse files
committed
Support adding attributes to each test
1 parent 622d703 commit f96b351

File tree

2 files changed

+30
-2
lines changed

2 files changed

+30
-2
lines changed

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,14 @@ The expression that is called on each file can also be a closure, for example:
117117
test_each_file! { in "./resources" => |c: &str| assert!(c.contains("Hello World")) }
118118
```
119119

120+
Multiple attributes can optionally be applied to each test, for example:
121+
122+
```rust
123+
test_each_file! { #[ignore, cfg(target_os = "linux")] in "./resources" => test }
124+
```
125+
120126
All the options above can be combined, for example:
121127

122128
```rust
123-
test_each_file! { for ["in", "out"] in "./resources" as example => |[a, b]: [&str; 2]| assert_eq!(a, b) }
129+
test_each_file! { #[ignore, cfg(target_os = "linux")] for ["in", "out"] in "./resources" as example => |[a, b]: [&str; 2]| assert_eq!(a, b) }
124130
```

src/lib.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ use std::ffi::OsString;
66
use std::path::{Path, PathBuf};
77
use syn::parse::{Parse, ParseStream};
88
use syn::punctuated::Punctuated;
9-
use syn::{bracketed, parse_macro_input, Expr, LitStr, Token};
9+
use syn::{bracketed, parse_macro_input, Expr, LitStr, Meta, Token};
1010
use unicode_ident::{is_xid_continue, is_xid_start};
1111

1212
struct TestEachArgs {
1313
path: LitStr,
1414
module: Option<Ident>,
1515
function: Expr,
1616
extensions: Vec<String>,
17+
attributes: Vec<Meta>,
1718
}
1819

1920
macro_rules! abort {
@@ -30,6 +31,20 @@ macro_rules! abort_token_stream {
3031

3132
impl Parse for TestEachArgs {
3233
fn parse(input: ParseStream) -> syn::Result<Self> {
34+
// Optionally parse attributes if `#` is used. Aborts if none are given.
35+
let attributes = input
36+
.parse::<Token![#]>()
37+
.and_then(|_| {
38+
let content;
39+
bracketed!(content in input);
40+
41+
match Punctuated::<Meta, Token![,]>::parse_separated_nonempty(&content) {
42+
Ok(attributes) => Ok(attributes.into_iter().collect()),
43+
Err(e) => abort!(e.span(), "Expected at least one attribute to be given."),
44+
}
45+
})
46+
.unwrap_or_default();
47+
3348
// Optionally parse extensions if the keyword `for` is used. Aborts if none are given.
3449
let extensions = input
3550
.parse::<Token![for]>()
@@ -81,6 +96,7 @@ impl Parse for TestEachArgs {
8196
module,
8297
function,
8398
extensions,
99+
attributes,
84100
})
85101
}
86102
}
@@ -226,6 +242,12 @@ fn generate_from_tree(
226242
quote!([#arguments])
227243
};
228244

245+
for attribute in &parsed.attributes {
246+
stream.extend(quote! {
247+
#[#attribute]
248+
});
249+
}
250+
229251
stream.extend(quote! {
230252
#[test]
231253
fn #file_name() {

0 commit comments

Comments
 (0)