You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Cargo特性标志有条件地执行模块级doctest?

处理Rust文档测试中特性依赖示例的条件运行需求

我最近在给一个带Cargo特性标志的Rust模块写文档时,遇到了这么个需求:希望所有特性相关的用法示例都能一直展示在文档里,让 crate 的使用者能清楚知道有这些功能可选,但只有当对应的特性启用时,这些示例才会被当作文档测试运行,没启用特性时就跳过,避免编译报错。

先给大家看看我最开始的代码实现:

初始代码

lib.rs

//! This crate has common utility functions
//! 
//! ```
//! assert_eq!(2, featureful::add_one(1));
//! ```
//! 
//! You may also want to use the feature flag `solve_halting_problem`:
//! 
//! ```
//! assert!(featureful::is_p_equal_to_np());
//! ```
pub fn add_one(a: i32) -> i32 { a + 1 }
#[cfg(feature = "solve_halting_problem")]
pub fn is_p_equal_to_np() -> bool { true }

Cargo.toml

[package]
name = "featureful"
version = "0.1.0"
authors = ["An Devloper <an.devloper@example.com>"]
[features]
solve_halting_problem = []
[dependencies]

遇到的问题

当我启用特性运行测试时,一切都正常,两个文档测试都能通过:

$ cargo test --features=solve_halting_problem
Doc-tests featureful

running 2 tests
test src/lib.rs - (line 7) ... ok
test src/lib.rs - (line 3) ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

但如果不启用特性直接跑测试,特性相关的那个示例就会编译失败:

$ cargo test
Doc-tests featureful

running 2 tests
test src/lib.rs - (line 7) ... FAILED
test src/lib.rs - (line 3) ... ok

failures:

---- src/lib.rs - (line 7) stdout ----
error[E0425]: cannot find function `is_p_equal_to_np` in module `featureful`
 --> src/lib.rs:8:21
  |
4 | assert!(featureful::is_p_equal_to_np());
  |         ^^^^^^^^^^^^^^^^ not found in `featureful`

我试过用ignore或者no_run修饰符,但这俩不管特性开没开都会生效——要么永远不运行这个测试,要么只展示代码不执行,完全达不到我想要的“特性启用时跑,禁用时不跑但仍展示”的效果。

完美解决方案

后来我发现,Rust的文档测试支持在代码块上添加条件编译属性,只要给特性相关的代码块加上cfg(feature = "xxx")的标识,就能实现我们的需求。

修改后的lib.rs代码如下:

//! This crate has common utility functions
//! 
//! ```
//! assert_eq!(2, featureful::add_one(1));
//! ```
//! 
//! You may also want to use the feature flag `solve_halting_problem`:
//! 
//! ```rust,cfg(feature = "solve_halting_problem")
//! assert!(featureful::is_p_equal_to_np());
//! ```
pub fn add_one(a: i32) -> i32 { a + 1 }
#[cfg(feature = "solve_halting_problem")]
pub fn is_p_equal_to_np() -> bool { true }

原理解释

在文档代码块的语言标记(这里是rust)后面加上,cfg(feature = "solve_halting_problem"),Cargo就会根据当前是否启用该特性来决定如何处理这个文档测试:

  • 当启用solve_halting_problem特性时,这个代码块会被当作正常的文档测试编译并执行;
  • 当未启用特性时,Cargo会自动过滤掉这个测试,不会尝试编译它,但文档里依然会完整展示这段代码,完全不影响用户查看特性对应的用法。

验证效果

现在再测试就完全符合预期了:

  • 不启用特性时,只会运行第一个通用的文档测试:
$ cargo test
Doc-tests featureful

running 1 test
test src/lib.rs - (line 3) ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out
  • 启用特性时,两个测试都会正常运行,和之前的成功结果一致。

之前我也看到过类似的问题讨论,但大多聚焦于条件编译的函数本身,而非模块文档里的示例处理,这个方法刚好能解决我们的特定需求。

内容的提问来源于stack exchange,提问作者Shepmaster

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:22:19