如何为私有模块编写文档测试

  • 本文关键字:文档 测试 模块 rust
  • 更新时间 :
  • 英文 :


我正在rust中编写一个库,它公开了一个使用私有模块的函数。现在,我可以使用以下命令呈现这个私有模块的文档:

cargo doc --document-private-items

现在,我有一个名为reader的模块,它包含一个结构,其中包含一些函数。模块本身是使用mod readerlib.rs文件导入的,其类型如下:use reader::BufferedOpenTypeFontReader;

现在,我想向BufferedOpenTypeFontReader结构添加一些文档,所以这就是它的实现:

/// A buffered `&[u8]` reader for reading an OpenType Font (OTF).
pub struct BufferedOpenTypeFontReader<'a> {
reader: BufReader<&'a [u8]>,
}
//# The basic implementation of the `OpenTypeFontByteSliceReader` struct.
impl<'a> BufferedOpenTypeFontReader<'a> {
//# Defines the constants which are required in this `impl` block.
const U32_SIZE: usize = 4; // The amount of bytes in a `u32`.
/// Create a new `BufferedOpenTypeFontReader<'a>` implementation which reads from the given `&[u8]`.
///
/// # Examples:
///  ```
/// use otfdecode::reader::BufferedOpenTypeFontReader;
///
/// let otf_bytes = [];
/// let otf_reader = BufferedOpenTypeFontReader::new(otf_bytes);
///  ```
pub fn new(data: &'a [u8]) -> Self {
Self {
reader: BufReader::new(data),
}
}
pub fn read_u32(&mut self) -> u32 {
let mut buffer = [0u8; Self::U32_SIZE];
self.reader.read_exact(&mut buffer).unwrap();
u32::from_be_bytes(buffer)
}
}

但是,当我运行cargo test时,我会遇到以下问题:

failures:
---- srcreader.rs - reader::BufferedOpenTypeFontReader::new (line 42) stdout ----
error[E0603]: module `reader` is private
--> srcreader.rs:43:16
|
4  | use otfdecode::reader::BufferedOpenTypeFontReader;
|                ^^^^^^ private module
|
note: the module `reader` is defined here
--> C:UserskevinDevelopmentgithub.comkdeconinckOTFDecodeappsrclib.rs:30:1
|
30 | mod reader;
|

如何在不公开模块reader的情况下为函数new编写文档测试?

来自文档测试文档:

请注意,它们仍然只会链接到您机箱中的公共物品;如果你需要测试私有项目,你需要编写一个单元测试。https://doc.rust-lang.org/rustdoc/documentation-tests.html

在撰写本文时,这在Rust中是不可能的。我对这个问题做了一些研究,以下是我的结论:

为什么这是一个问题

文档测试被编译为独立的外部单元。首先编译库,然后将doctest编译单元链接到库。编译doctest时,库的行为与外部库完全相同。即使是pub(crate)也不起作用,因为根据编译器的说法,它实际上是一个单独的库。

如果你把文档看作是一种帮助人们使用你的图书馆的产品,这在哲学上是有意义的。他们将使用你的库作为外部,所以让库的行为与他们一样是有意义的。这样做的缺点是,它有点阻碍为其他目的编写(好的(文档:从长远来看,使库本身更容易维护。

有一些声音想要改变这种状况。特别是,请参阅此问题。但在撰写本文时,它还没有得到太多的关注。

解决方法

真的没有好的解决办法。这些都是人们想出的变通办法,但没有一个是令人满意的:

  • 不要编写使用私有符号的文档测试。相反,使用单元测试。然而,这通常会使您的文档变得更糟
  • ignore添加到使用专用符号的doctest中。这样做的缺点是,如果您以后进行更改,您不确定文档化的示例是否仍然有效(除非您将代码复制到单元测试中,但随后您有重复的代码(。就像这样:
/// Computes the sum of two numbers.
///
/// # Examples
/// ```ignore
/// use calculator::adder::private_adder;
/// assert_eq!(5, private_adder(2, 3));
/// ```
fn private_adder(left: i32, right: i32) { left + right }
  • 让你的符号全部公开,但"隐藏";它位于detailprivate子模块下,这样库的用户就可以清楚地知道不应该使用它。这样做的缺点是,它仍然允许库的用户发现和使用这些功能,认为它们很聪明,然后可能会破坏东西。它还扰乱了您的公共API,并且如果您关心的是库内部的秘密业务逻辑,则可能会揭示更多信息
  • 有一个名为"可见性"的机箱,允许您根据特征更改符号的可见性。使用此功能,如果启用了该功能,则可以将每个专用符号公开。然后,您可以通过在命令中添加doctest_privates功能来编译doctest:cargo test --doc --features doctest_privates。然而,这需要将以下属性添加到您的每个私有符号(或者至少添加到您希望在doctest中使用的所有模块、类和函数(:
/// Computes the sum of two numbers.
///
/// # Examples
/// ```
/// use calculator::adder::private_adder;
/// assert_eq!(5, private_adder(2, 3));
/// ```
#[cfg_attr(feature = "document_privates", visibility::make(pub))]
fn private_adder(left: i32, right: i32) { left + right }

最新更新