原文作者@GuillaumeGomez
虽然现在写这篇博文可能有点晚,因为#[cfg(doctest)]
从Rust 1.40开始就已经很稳定,
但是我觉得告诉大家这个宏的特征和用法非常重要。
这个宏什么东西?
首先说说,这个宏是拿来做什么用的,什么时候用上。
答案很简单:用来生成文档是做文档内代码测试的,也就是我们运行rustdoc --test
或者cargo test
运行到doc
部分的时候,设置了这个宏内的代码就会被运行。
为什么要用这个宏?
然后我们为什么要在乎这个宏呢?它能做什么呢?
答案就是:这个宏让你可以做一些特殊的校验坚持,特别是当rustdoc在测试模式下运行的时候.
比如如果你在一个名为some_file.md的文件(其实是文档)中引用了一些代码段并且你想测试这些代码, 你就可以在你文档的代码段中加入如下宏和代码:
#[cfg(doctest)]
macro_rules! doc_check {
($x:expr) => {
#[doc = $x]
extern {}
};
}
#[cfg(doctest)]
doc_check!(include_str!("some_file.md")));
这段文档中的代码是怎么意思呢? 很简单,就是当我们在extern
代码块运行的时候,
我们其实在将some_file.md文档内容当作文档注释倒入了。
也就是说当通过entern
倒入的文档包含了Rust语言块的时候,
这些Rust语言将会在运行cargo test
的时候被测试。
#[cfg(doctest)]宏强大的地方在于,这些文档内代码只在测试运行test
的时候
被运行,在所有的非test
测试运行或编译的时候将不会被运行或被测试。
不过,使用这个宏唯一需要担心的就是要绕开带#[doc = ...]
标签的一些限制。
#[doc = ...]
只接受字符串,别的(包括夹杂的代码段)一概不理会。
这就是为什么要使用宏来实现在文档中识别代码段并还能测试的功能。
我想我们一再强调的就是:在你写的Rust工程技术文档里包含代码例子对每一个人都非常重要, 包括对写代码的你自己都意义非法。而且更重要的是,这些文档中的代码真正的被测试了, 这保证了文档中的代码是测试过,跑得起来的,意味着这个宏还可以防止文档中的代码错误 或者随着研发的推进没有被及时测试而过时了。
有什么同样好的替代品吗?
哈,答案是肯定的,那就是本人不久前开发的doc-comment 软件包,让这种场景功能应用起来超级简单:
#[cfg(doctest)]
doctest!("some_file.md");
这个宏虽然不是什么革命性的创新,但是它的确能让代码读起来简单很多。
doc-comment
软件包的另一个优点就是它的依赖库只有在测试运行的时候才被下载和引用。
你可以在Cargo.toml工程文件的[dev-dependencies]
段中添加如下依赖库代码:
[dev-dependencies]
doc-comment = "0.3"
非常简单!
结论
虽然不是什么巨大的工程,但是这些宏是rustdoc工具非常有趣和实用的补充。 感觉不是很多人了解这些宏的功能,写这篇博文想让这些宏可以被更深入的了解并应用。
大家相望于代码江湖~~
Ext Link: https://blog.guillaume-gomez.fr/articles/2020-03-07+cfg%28doctest%29+is+stable+and+you+should+use+it
评论区
写评论还没有评论