是否有一种方法使单元/集成测试在给定的时间后失败?



我正在Rust中实现一个虚拟机作为练习。一些集成测试在虚拟机上运行小程序,并对最终结果做出断言。

然而,可能会发生一个错误导致机器陷入无限循环,这意味着cargo test永远不会完成。

是否有一种方法使单元/集成测试在给定的时间后失败?也许是类似于#[should_panic]的东西,但是,不如说,#[time_limit(500)]?

在SirDarius的评论中提到的带有#[timeout(<ms>)]宏的测试箱可能是一个比以下更简单的解决方案。

作为替代方案,有一个允许创建运行闭包的进程的crate,它具有一些与测试相关的特性。与线程不同,如果进程运行时间过长,就会被终止。

crate procspawn有这个闭包特性,以及其他一些很好的特性,这些特性对于需要超时的测试很有用。这些特性中的另一个是对子进程中调用的代码的返回值进行序列化。测试代码可以以一种非常直接的方式获得结果并检查它。

要测试的代码:

use std::thread;
use std::time::Duration;
fn runs_long() -> i32
{
thread::sleep(Duration::from_millis(5000));
42
}

在同一个文件中,我们可以添加一些带有超时的测试:

#[cfg(test)]
mod tests {
use std::time::Duration;
use procspawn;

use crate::*;

procspawn::enable_test_support!();

#[test]
fn runs_long_passes()
{
let handle = procspawn::spawn((), |_| runs_long());

match handle.join_timeout(Duration::from_millis(6000)) {
Ok(result) => assert_eq!(result, 42),
Err(e)     => panic!("{}", e),
}
}

#[test]
fn runs_long_fails()
{
let handle = procspawn::spawn((), |_| runs_long());

match handle.join_timeout(Duration::from_millis(1000)) {
Ok(result) => assert_eq!(result, 42),
Err(e)     => panic!("{}", e),
}
}
}

在命令行上使用cargo test运行测试,我们得到:

running 3 tests
test tests::procspawn_test_helper ... ok
test tests::runs_long_fails ... FAILED
test tests::runs_long_passes ... ok
failures:
---- tests::runs_long_fails stdout ----
thread 'tests::runs_long_fails' panicked at 'process spawn error: timed out', src/main.rs:50:17
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

failures:
tests::runs_long_fails
test result: FAILED. 2 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 6.01s
error: test failed, to rerun pass '--bin procspawn'

要启用测试支持特性,请在您的Cargo中包含以下内容。toml文件:

[dependencies]
procspawn = { version = "0.10", features = ["test-support"] }

最新更新