Skip to content

JasterV/test-context

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

68 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

crates.io Documentation License Github

test-context

A library for providing custom setup/teardown for Rust tests without needing a test harness.

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.

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 or tokio::test.

#[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:

#[test_context(MyAsyncContext)]
#[tokio::test]
async fn my_test(ctx: &mut MyAsyncContext) {}

Invalid:

#[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:

[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:

 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

About

A Rust library to allow for easy setup/teardown implementations for tests

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 8

Languages