Rust执行测试时如何打印tracing crate生成的日志输出?
Rust 测试场景下打印 tracing 日志的配置方法
Rust 内置测试框架默认会捕获测试线程的所有标准输出/标准错误,只有测试失败时才会把捕获的内容打印出来;加上 tracing 本身不会自动输出日志,必须提前注册日志收集器,所以默认跑测试看不到 tracing 打出来的日志,按下面步骤配置即可:
1. 引入测试场景需要的依赖
把日志输出相关的包加到开发依赖里,不会影响正式构建的体积:
[dev-dependencies] tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
2. 写可复用的一次性初始化函数
tracing 的全局日志收集器只能设置一次,多测试并行跑的时候重复初始化会报错,所以写个通用初始化函数,用try_init避免重复初始化触发panic,同时用官方提供的测试专用输出适配器对接测试框架的捕获逻辑:
// 可以放在tests目录下的公共模块,或者每个测试文件的顶部 fn init_test_tracing() { let _ = tracing_subscriber::fmt() // 对接测试输出捕获机制,测试失败时自动带出捕获的日志 .with_test_writer() // 支持通过RUST_LOG环境变量控制日志级别,也可以直接写死规则 .with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) // 用try_init而非init,重复初始化时不会panic .try_init(); }
.with_test_writer()是tracing-subscriber专门给测试场景做的适配,不用自己手动处理标准输出句柄,比直接往stdout写日志兼容性好很多。
3. 在测试用例开头调用初始化
每个测试用例执行前先调一遍初始化即可,重复调用也不会出问题:
#[test] fn test_biz_logic() { init_test_tracing(); // 正常写测试逻辑,用tracing的宏打日志即可 tracing::info!("测试启动,当前入参:{:?}", test_params); tracing::debug!("中间计算结果:{}", mid_val); // ... 其余测试逻辑 }
4. 运行测试查看日志
分两种常用场景:
- 需要实时看到所有日志(不管测试成功失败):跑测试时给测试二进制传
--nocapture参数,关闭输出捕获:# 跑所有测试并实时打印日志 cargo test -- --nocapture # 只跑指定测试并打印日志 cargo test test_biz_logic -- --nocapture - 不需要实时看日志:不用加任何额外参数,默认配置下如果测试执行失败,框架会自动把这个测试运行期间捕获的所有tracing日志和失败报错、栈追踪一起打印出来,测试通过的话日志不会显示,不会干扰干净的测试结果输出。
如果需要调整日志级别,跑测试前加RUST_LOG环境变量即可,比如要打印debug及以上级别的日志:
RUST_LOG=debug cargo test -- --nocapture
要是不想每次跑都设环境变量,也可以在初始化的时候直接写死过滤规则,把from_default_env()替换成tracing_subscriber::EnvFilter::new("info")就会默认打印info及以上级别的日志。
常见踩坑提醒:别用init()替换try_init(),多线程并行跑测试的时候,多个测试同时触发初始化,init()会因为全局收集器已存在直接panic,导致测试无意义失败。
内容的提问来源于stack exchange,提问作者Thorkil Værge
相关产品推荐
相关产品推荐

