Skip to content

Commit 464cd41

Browse files
rookiecjJasterV
authored andcommitted
feat: Support generic types in test_context macro (#44)
- Allow using test_context with generic contexts like MyContext<T>
1 parent 7cab727 commit 464cd41

File tree

3 files changed

+61
-7
lines changed

3 files changed

+61
-7
lines changed

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,22 @@ impl TestContext for MyContext {
2929
fn test_works(ctx: &mut MyContext) {
3030
assert_eq!(ctx.value, "Hello, World!");
3131
}
32+
33+
struct MyGenericContext<T> {
34+
value: T
35+
}
36+
37+
impl TestContext for MyGenericContext<u32> {
38+
fn setup() -> MyGenericContext<u32> {
39+
MyGenericContext { value: 1 }
40+
}
41+
}
42+
43+
#[test_context(MyGenericContext<u32>)]
44+
#[test]
45+
fn test_generic_type(ctx: &mut MyGenericContext<u32>) {
46+
assert_eq!(ctx.value, 1);
47+
}
3248
```
3349

3450
Alternatively, you can use `async` functions in your test context by using the

test-context-macros/src/args.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
use syn::{parse::Parse, Ident, Token};
1+
use syn::{parse::Parse, Token, Type};
22

33
pub(crate) struct TestContextArgs {
4-
pub(crate) context_type: Ident,
4+
pub(crate) context_type: Type,
55
pub(crate) skip_teardown: bool,
66
}
77

88
impl Parse for TestContextArgs {
99
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
1010
let mut skip_teardown = false;
11-
let mut context_type: Option<Ident> = None;
11+
let mut context_type: Option<Type> = None;
1212

1313
while !input.is_empty() {
1414
let lookahead = input.lookahead1();
@@ -18,10 +18,8 @@ impl Parse for TestContextArgs {
1818
}
1919
let _ = input.parse::<kw::skip_teardown>()?;
2020
skip_teardown = true;
21-
} else if lookahead.peek(Ident) {
22-
if context_type.is_some() {
23-
return Err(input.error("expected only a single type identifier"));
24-
}
21+
} else if context_type.is_none() {
22+
// Parse any valid Rust type, including generic types
2523
context_type = Some(input.parse()?);
2624
} else if lookahead.peek(Token![,]) {
2725
let _ = input.parse::<Token![,]>()?;

test-context/tests/test.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,43 @@ async fn test_async_skip_teardown(mut _ctx: TeardownPanicContext) {}
131131
#[test_context(TeardownPanicContext, skip_teardown)]
132132
#[test]
133133
fn test_sync_skip_teardown(mut _ctx: TeardownPanicContext) {}
134+
135+
struct GenericContext<T> {
136+
contents: T,
137+
}
138+
139+
impl TestContext for GenericContext<u32> {
140+
fn setup() -> Self {
141+
Self { contents: 1 }
142+
}
143+
}
144+
145+
impl TestContext for GenericContext<String> {
146+
fn setup() -> Self {
147+
Self { contents: format!("hello world") }
148+
}
149+
}
150+
151+
impl AsyncTestContext for GenericContext<u64> {
152+
async fn setup() -> Self {
153+
Self { contents: 1 }
154+
}
155+
}
156+
157+
#[test_context(GenericContext<u32>)]
158+
#[test]
159+
fn test_generic_with_u32(ctx: &mut GenericContext<u32>) {
160+
assert_eq!(ctx.contents, 1);
161+
}
162+
163+
#[test_context(GenericContext<String>)]
164+
#[test]
165+
fn test_generic_with_string(ctx: &mut GenericContext<String>) {
166+
assert_eq!(ctx.contents, "hello world");
167+
}
168+
169+
#[test_context(GenericContext<u64>)]
170+
#[tokio::test]
171+
async fn test_async_generic(ctx: &mut GenericContext<u64>) {
172+
assert_eq!(ctx.contents, 1);
173+
}

0 commit comments

Comments
 (0)