我在src
目录中有一个包含生产代码的箱子,在tests
目录中有一个集成测试。生产代码使用log
个宏。
我想在运行集成测试时初始化一个全局记录器(例如env_logger::init().unwrap();
)
有几个测试,测试顺序没有定义,所以我不知道应该在哪个测试中放置初始化命令。
有什么方法可以做得很好吗?也许通过覆盖测试main
函数?
答案 0 :(得分:6)
您可以使用以下内容:
use std::sync::{Once, ONCE_INIT};
static INIT: Once = ONCE_INIT;
/// Setup function that is only run once, even if called multiple times.
fn setup() {
INIT.call_once(|| {
env_logger::init().unwrap();
});
}
然后只需在每次测试开始时调用setup()
。
最初基于this blogpost。
答案 1 :(得分:5)
目前没有好办法做这种内置的事情。
您可以编写一个宏,在每次测试之前插入某种初始化调用,但是它与它一样接近。
答案 2 :(得分:1)
现在,您可以在每个测试的顶部重新初始化记录器并忽略错误。它不是一个漂亮的解决方案,但它的工作原理非常安全。
let _ = env_logger::init();
// your test code...
答案 3 :(得分:0)
除了Danilo Bargen的评论之外,您还可以将其写成较短的形式:
use std::sync::Once;
static INIT: Once = Once::new();
fn setup() {
INIT.call_once(env_logger::init);
}
答案 4 :(得分:-1)
我观察cargo test
按字母顺序运行测试,因此我设计了一个非常脏的黑客来初始化记录器。
aaa_testing
的模块,位于箱子的根部。在模块内部,我编写了记录器初始化程序。
#[test]
fn initialize_logger() {
env_logger::init();
}
是的,我确实创建了一个始终通过的测试,但是如果您想要初始化记录器的测试,可以执行assert!(env_logger::try_init().is_ok());
Shepmaster指出cargo test
异步运行测试并且可能使前几个测试的记录不可靠。为了防止这种情况,可以在同一个线程中运行测试。 (这会导致性能问题,因此,如果您需要多个线程来测试项目,则不应使用此答案。)
如果要控制同时运行的测试用例的数量,请将
--test-threads
选项传递给测试二进制文件:cargo test -- --test-threads=1
答案 5 :(得分:-1)
latest documentation has a recommendation:
#[cfg(test)]
mod tests {
fn init() {
let _ = env_logger::builder().is_test(true).try_init();
}
#[test]
fn it_works() {
info!("This record will be captured by `cargo test`");
assert_eq!(2, 1 + 1);
}
}