7个版本
0.3.3 | 2023年1月9日 |
---|---|
0.3.2 | 2023年1月8日 |
0.2.1 | 2022年12月31日 |
0.1.0 | 2022年12月23日 |
#16 in #guard
8KB
这是一个属性宏,用于使用Tokio进行测试,具有案例和异步守卫。
这个crate提供了一个简单的属性宏 #[test_with_tokio::please]
,允许你编写在Tokio中运行异步代码之前先运行一些非异步代码的测试。这类似于 #[tokio::test]
,但有两大特性:可以在启动Tokio运行时之前运行异步代码,并且可以编写一个测试来生成多个测试,这些测试处理相同测试的多个案例。通过一些工作,这可以使你并行运行大多数测试,但有一些测试不能并行运行。
示例
在最基本的情况下,这个crate使你能够轻松编写在运行异步代码之前先运行非异步代码的测试。
// The async in `async fn` below is optional and ignored.
#[test_with_tokio::please]
async fn test_me() {
println!("This code will be run before the tokio runtime is started.");
async_std::println!("This code will be run with a tokio runtime").await;
}
持有锁
这个crate的动机是允许使用锁来并行运行测试
static DIRECTORY_LOCK: std::sync::RwLock<()> = std::sync::RwLock::new(());
#[test_with_tokio::please]
fn test_run_exclusively() {
let _guard = DIRECTORY_LOCK.write().unwrap();
async_std::println!("This code will be run with exclusive access to the directory.").await;
}
#[test_with_tokio::please] fn test_run_cooperatively() {
let _guard = DIRECTORY_LOCK.read().unwrap();
async_std::println!("This code will be run concurrently with other cooperative tests..").await;
}
你可能想知道,为什么不在 async
块内获取锁,或者也许只是在一个带有 #[tokio::test]
标记的函数内简单地获取锁?答案是缺少 async
Drop
。这意味着测试可能不会在Tokio运行时退出后才完全清理,这意味着你仍然可能在测试中遇到竞态条件,同时并发获取锁。
多个案例
如果你可以编写通过将变量分配给 match CASE { ... }
生成多个相关测试的代码,其中每个案例都匹配一个有效的标识符后缀的字符串字面量。
#[test_with_tokio::please]
fn test_contains() {
let container = match CASE {
"hello" => "hello world",
"this_test" => vec!["this_test"],
};
assert!(container.contains(CASE));
}
此示例将创建两个函数,每个函数都带有 #[test]
标记,一个命名为 test_contains_hello
,另一个 test_contains_this_test
。第一个函数的主体将类似于
#[test]
fn test_contains_hello() {
const CASE: &str = "hello";
let container = "hello world";
assert!(container.contains(CASE));
}
依赖
~1.5MB
~35K SLoC