如何在Rust中运行任何测试之前运行设置代码?

kit*_*yst 3 unit-testing rust

我有一个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_unwindhttps : //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)

函数名并不重要,你可以任意命名。


Jus*_*nen 9

没有内置功能可以做到这一点,但这应该会有所帮助(您需要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)