如何在Rust文档测试中启用默认被编译剔除的代码?
场景说明
我维护一个Rust crate,其中包含一个foo模块,仅在启用enable_foo特性时才编译(该特性不默认开启)。但我希望执行cargo doc时能生成该模块的文档,因此用了如下条件编译:
#[cfg(any(feature="enable_foo", doc))] mod foo;
foo模块内的函数带有文档测试,最小示例如下:
/// Does nothing. /// /// ``` /// # use crate::foo::do_nothing; /// do_nothing(); /// ``` fn do_nothing() {}
当前问题
当未显式启用enable_foo特性时,执行cargo test会失败。原因是:cargo doc会将foo模块纳入文档生成,文档测试扫描阶段能找到该模块的测试用例;但运行测试时,由于enable_foo未启用,foo模块被编译剔除,导致测试无法执行对应代码。
次优规避方案
可以通过调整条件编译,让foo模块仅在特性启用,或仅生成文档(非文档测试扫描阶段)时才编译,这样文档测试不会扫描到该模块的测试用例:
#[cfg(any(feature="enable_foo", all(doc, not(doctest))))] mod foo;
但这只是规避问题,我真正想要的是:即使enable_foo特性被禁用,运行文档测试时也能编译foo模块。
无效尝试
我尝试过直接把doctest加入条件编译,但没有效果:
#[cfg(any(feature="enable_foo", doc, doctest))] mod foo;
这是因为doctest配置标志仅在扫描文档测试的阶段被设置,在实际运行文档测试时并不会生效。换成test标志也无法改变行为。
核心疑问
有没有办法在运行文档测试时(而非扫描阶段),让原本被特性 gated 的代码被编译?可以是源代码层面的条件编译属性,或者Cargo层面的配置,让文档测试运行时强制启用enable_foo特性。
我试过一种本地可行但存疑的Cargo方案:将当前crate作为自身的开发依赖并启用enable_foo特性,但这可能导致测试使用的是开发依赖中的代码而非本地正在开发的代码,一旦crate发布,测试会针对已发布版本而非当前开发版本,显然不符合预期。
(注:已有相关问题讨论测试时启用特性,但均针对多crate交互场景,不适用于本次单crate的情况)
内容的提问来源于stack exchange,提问作者ais523

