Attribute Macro maybe_async::test

source ·
#[test]
Expand description

Handy macro to unify test code of sync and async code

Since the API of both sync and async code are the same, with only difference that async functions must be awaited. So it’s tedious to write unit sync and async respectively.

This macro helps unify the sync and async unit test code. Pass the condition to treat test code as sync as the first argument. And specify the condition when to treat test code as async and the lib to run async test, e.x. async-std::test, tokio::test, or any valid attribute macro.

ATTENTION: do not write await inside a assert macro

  • Examples
#[maybe_async::maybe_async]
async fn async_fn() -> bool {
    true
}

#[maybe_async::test(
    // when to treat the test code as sync version
    feature="is_sync",
    // when to run async test
    async(all(not(feature="is_sync"), feature="async_std"), async_std::test),
    // you can specify multiple conditions for different async runtime
    async(all(not(feature="is_sync"), feature="tokio"), tokio::test)
)]
async fn test_async_fn() {
    let res = async_fn().await;
    assert_eq!(res, true);
}

// Only run test in sync version
#[maybe_async::test(feature = "is_sync")]
async fn test_sync_fn() {
    let res = async_fn().await;
    assert_eq!(res, true);
}

The above code is transcripted to the following code:


// convert to sync version when sync condition is met, keep in async version when corresponding
// condition is met
#[cfg_attr(feature = "is_sync", must_be_sync, test)]
#[cfg_attr(
    all(not(feature = "is_sync"), feature = "async_std"),
    must_be_async,
    async_std::test
)]
#[cfg_attr(
    all(not(feature = "is_sync"), feature = "tokio"),
    must_be_async,
    tokio::test
)]
async fn test_async_fn() {
    let res = async_fn().await;
    assert_eq!(res, true);
}

// force converted to sync function, and only compile on sync condition
#[cfg(feature = "is_sync")]
#[test]
fn test_sync_fn() {
    let res = async_fn();
    assert_eq!(res, true);
}