mirror of
https://codeberg.org/JasterV/test-context.git
synced 2026-04-26 18:10:06 +00:00
152 lines
4 KiB
Markdown
152 lines
4 KiB
Markdown
[](https://crates.io/crates/test-context)
|
|
[](https://docs.rs/test-context)
|
|

|
|
[](https://github.com/markhildreth/test-context/actions)
|
|
|
|
# test-context
|
|
|
|
A library for providing custom setup/teardown for Rust tests without needing a test harness.
|
|
|
|
```rust
|
|
use test_context::{test_context, TestContext};
|
|
|
|
struct MyContext {
|
|
value: String
|
|
}
|
|
|
|
impl TestContext for MyContext {
|
|
fn setup() -> MyContext {
|
|
MyContext { value: "Hello, World!".to_string() }
|
|
}
|
|
|
|
fn teardown(self) {
|
|
// Perform any teardown you wish.
|
|
}
|
|
}
|
|
|
|
#[test_context(MyContext)]
|
|
#[test]
|
|
fn test_works(ctx: &mut MyContext) {
|
|
assert_eq!(ctx.value, "Hello, World!");
|
|
}
|
|
|
|
struct MyGenericContext<T> {
|
|
value: T
|
|
}
|
|
|
|
impl TestContext for MyGenericContext<u32> {
|
|
fn setup() -> MyGenericContext<u32> {
|
|
MyGenericContext { value: 1 }
|
|
}
|
|
}
|
|
|
|
#[test_context(MyGenericContext<u32>)]
|
|
#[test]
|
|
fn test_generic_type(ctx: &mut MyGenericContext<u32>) {
|
|
assert_eq!(ctx.value, 1);
|
|
}
|
|
```
|
|
|
|
Alternatively, you can use `async` functions in your test context by using the
|
|
`AsyncTestContext`.
|
|
|
|
```rust
|
|
use test_context::{test_context, AsyncTestContext};
|
|
|
|
struct MyAsyncContext {
|
|
value: String
|
|
}
|
|
|
|
impl AsyncTestContext for MyAsyncContext {
|
|
async fn setup() -> MyAsyncContext {
|
|
MyAsyncContext { value: "Hello, World!".to_string() }
|
|
}
|
|
|
|
async fn teardown(self) {
|
|
// Perform any teardown you wish.
|
|
}
|
|
}
|
|
|
|
#[test_context(MyAsyncContext)]
|
|
fn test_works(ctx: &mut MyAsyncContext) {
|
|
assert_eq!(ctx.value, "Hello, World!");
|
|
}
|
|
```
|
|
|
|
The `AsyncTestContext` works well with async test wrappers like
|
|
[`actix_rt::test`](https://docs.rs/actix-rt/1.1.1/actix_rt/attr.test.html) or
|
|
[`tokio::test`](https://docs.rs/tokio/1.0.2/tokio/attr.test.html).
|
|
|
|
```rust
|
|
#[test_context(MyAsyncContext)]
|
|
#[tokio::test]
|
|
async fn test_works(ctx: &mut MyAsyncContext) {
|
|
assert_eq!(ctx.value, "Hello, World!");
|
|
}
|
|
```
|
|
|
|
### Attribute order
|
|
|
|
Place `#[test_context(...)]` before other test attributes like `#[tokio::test]` or `#[test]`.
|
|
|
|
Why: Attributes expand in source order. `#[test_context]` generates a wrapper and reattaches
|
|
the remaining attributes to it. It must run first so the test attribute applies to the wrapper
|
|
that runs setup/teardown.
|
|
|
|
Valid:
|
|
|
|
```rust
|
|
#[test_context(MyAsyncContext)]
|
|
#[tokio::test]
|
|
async fn my_test(ctx: &mut MyAsyncContext) {}
|
|
```
|
|
|
|
Invalid:
|
|
|
|
```rust
|
|
#[tokio::test]
|
|
#[test_context(MyAsyncContext)]
|
|
async fn my_test(ctx: &mut MyAsyncContext) {}
|
|
```
|
|
|
|
## Using AsyncTestContext in sync tests that require Tokio
|
|
|
|
By default, when you use an `AsyncTestContext` in a synchronous test (no `#[tokio::test]`),
|
|
this crate runs `setup`/`teardown` using the `futures` executor. If your context calls
|
|
Tokio-only APIs (e.g., `tokio::time::sleep`, timers, or Tokio sockets) during setup/teardown,
|
|
enable the optional `tokio-runtime` feature so those steps run inside a Tokio runtime:
|
|
|
|
```toml
|
|
[dependencies]
|
|
test-context = { version = "0.4", features = ["tokio-runtime"] }
|
|
```
|
|
|
|
With this feature, the crate tries to reuse an existing runtime; if none is present, it creates
|
|
an ephemeral current-thread Tokio runtime around `setup` and `teardown` for sync tests. Async
|
|
tests annotated with `#[tokio::test]` continue to work as usual without the feature.
|
|
|
|
## Skipping the teardown execution
|
|
|
|
If what you need is to take full **ownership** of the context and don't care about the
|
|
teardown execution for a specific test, you can use the `skip_teardown` keyword on the macro
|
|
like this:
|
|
|
|
```rust
|
|
use test_context::{test_context, TestContext};
|
|
|
|
struct MyContext {}
|
|
|
|
impl TestContext for MyContext {
|
|
fn setup() -> MyContext {
|
|
MyContext {}
|
|
}
|
|
}
|
|
|
|
#[test_context(MyContext, skip_teardown)]
|
|
#[test]
|
|
fn test_without_teardown(ctx: MyContext) {
|
|
// Perform any operations that require full ownership of your context
|
|
}
|
|
```
|
|
|
|
License: MIT
|