test_context/
lib.rs

1#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))]
2
3// Reimported to allow for use in the macro.
4pub use futures;
5
6pub use test_context_macros::test_context;
7
8/// The trait to implement to get setup/teardown functionality for tests.
9pub trait TestContext
10where
11    Self: Sized,
12{
13    /// Create the context. This is run once before each test that uses the context.
14    fn setup() -> Self;
15
16    /// Perform any additional cleanup of the context besides that already provided by
17    /// normal "drop" semantics.
18    fn teardown(self) {}
19}
20
21/// The trait to implement to get setup/teardown functionality for async tests.
22pub trait AsyncTestContext
23where
24    Self: Sized,
25{
26    /// Create the context. This is run once before each test that uses the context.
27    fn setup() -> impl std::future::Future<Output = Self> + Send;
28
29    /// Perform any additional cleanup of the context besides that already provided by
30    /// normal "drop" semantics.
31    fn teardown(self) -> impl std::future::Future<Output = ()> + Send {
32        async {}
33    }
34}
35
36// Automatically impl TestContext for anything Send that impls AsyncTestContext.
37//
38// A future improvement may be to use feature flags to enable using a specific runtime
39// to run the future synchronously. This is the easiest way to implement it, though, and
40// introduces no new dependencies.
41impl<T> TestContext for T
42where
43    T: AsyncTestContext + Send,
44{
45    fn setup() -> Self {
46        futures::executor::block_on(<T as AsyncTestContext>::setup())
47    }
48
49    fn teardown(self) {
50        futures::executor::block_on(<T as AsyncTestContext>::teardown(self))
51    }
52}