Rust同时包含库和二进制目标时#[cfg(test)]不生效解决方法
问题:Rust库的
#[cfg(test)]在集成测试/二进制文件测试中不生效 开发同时包含库目标和二进制目标的Rust项目时,库中通过#[cfg(test)]属性条件编译了两套panic handler:一套供生产环境使用,一套供测试使用。这套逻辑在src/lib.rs的单元测试中运行正常,但运行tests/目录下的集成测试或是src/main.rs中的测试时,始终引入的是生产环境的panic handler,即这些场景下lib.rs编译时test=false,该行为是否可以通过配置调整?
最小复现示例
目录结构
Cargo.toml src/lib.rs src/main.rs
Cargo.toml配置
# Cargo.toml ... [lib] name = "kernel" [[bin]] path = "src/main.rs" name = "titanium"
src/main.rs代码
// main.rs fn main() { println!("Hello, world!"); } #[test] fn it_works() { assert_eq!(kernel::hello(), "Hello!".to_string()); }
src/lib.rs代码
// lib.rs #[cfg(test)] pub fn hello() -> String { "Hello!".to_string() } #[cfg(not(test))] pub fn hello() -> String { "Goodbye!".to_string() } #[test] fn it_works() { assert_eq!(hello(), "Hello!".to_string()) }
解决方案
该行为对99%的使用场景都符合预期,仅不适用于无界面VM中运行的玩具操作系统测试套件这类特殊场景(仅向宿主机stdout输出内容),可以通过自定义feature切换panic handler实现需求,调整方案如下:
调整后配置
Cargo.toml新增feature定义
# Cargo.toml ... [features] test_qemu_headless = []
调整后src/lib.rs代码
二进制文件代码无需改动,仅修改库代码即可:
// lib.rs #[cfg(feature = "test_qemu_headless")] pub fn hello() -> String { "Hello!".to_string() } #[cfg(not(feature = "test_qemu_headless"))] pub fn hello() -> String { "Goodbye!".to_string() } #[test] fn it_works() { assert_eq!(hello(), "Hello!".to_string()) }
测试执行命令
cargo test --features test_qemu_headless
内容的提问来源于stack exchange,提问作者Christian Kuhl
相关产品推荐
相关产品推荐

