我有一个Rust应用程序(一个简单的解释器),在环境可用之前,需要进行一些设置(初始化存储库)。
我知道Rust是以多线程方式运行其测试(通过货物测试)的,所以我需要在运行任何测试之前初始化存储库。我还需要每次运行只执行一次,而不是每次测试之前。
在Java的JUnit中,这可以通过@BeforeClass(或JUnit 5中的@BeforeAll)方法完成。我如何在Rust中达到同一目的?
val*_*tev 14
只是为了给人们更多的想法(例如,如何不在setup每个测试中调用),您可以做的另一件事是编写一个这样的助手:
fn run_test<T>(test: T) -> ()
where T: FnOnce() -> () + panic::UnwindSafe
{
setup();
let result = panic::catch_unwind(|| {
test()
});
teardown();
assert!(result.is_ok())
}
Run Code Online (Sandbox Code Playgroud)
然后,在您自己的测试中,您将像这样使用它:
#[test]
fn test() {
run_test(|| {
let ret_value = function_under_test();
assert!(ret_value);
})
}
Run Code Online (Sandbox Code Playgroud)
您可以在此处阅读有关UnwindSafetrait 的更多信息catch_unwind:https : //doc.rust-lang.org/std/panic/fn.catch_unwind.html
我在Eric Opines 的这篇中等文章中找到了这个测试助手的最初想法。
此外,还有一个rstest crate,它具有类似 pytest 的装置,您可以将其用作设置代码(结合Jussi Kukkonen 的回答:
use std::sync::Once;
use rstest::rstest;
static INIT: Once = Once::new();
pub fn setup() -> () {
INIT.call_once(|| {
// initialization code here
});
}
#[rstest]
fn should_success(setup: ()) {
// do your test
}
Run Code Online (Sandbox Code Playgroud)
也许有一天 rstest 将获得范围支持并且Once不再需要。
Bre*_*loy 12
如果您使用ctor crate,则可以利用将在运行任何测试之前运行的全局构造函数。
这是初始化流行的env_logger crate的示例(假设您已将其添加ctor到文件中的[dev-dependencies]部分Cargo.toml):
#[cfg(test)]
#[ctor::ctor]
fn init() {
env_logger::init();
}
Run Code Online (Sandbox Code Playgroud)
函数名并不重要,你可以任意命名。
没有内置功能可以做到这一点,但这应该会有所帮助(您需要initialize() 在每次测试的开始时致电):
use std::sync::Once;
static INIT: Once = Once::new();
pub fn initialize() {
INIT.call_once(|| {
// initialization code here
});
}
Run Code Online (Sandbox Code Playgroud)