我正在实现一个具有内部不变式的数据 struct ,我想通过测试来覆盖它.这个不变量是数据 struct 的一部分;因此,如果实现得当,数据 struct 用户的任何操作序列都不会违反它,但显然我仍然希望对其进行测试.

目前,我只是使用debug_assert!来测试不变量,我的代码看起来像这样:

fn test_invariant(&self) -> bool { 
    // some computations
}

fn some_algorithm(&self) {
    // some code

    debug_assert!(self.test_invariant());

    // more code
}

然而,由于test_invariant在计算上有些昂贵,并且不应该在用户代码中触发,所以我希望断言只在我自己的测试中是活动的.此外,不变量是算法的一部分,因此断言不能很容易地移到单元测试中(您可以将其视为在实现堆排序的就地版本时测试堆不变量).在铁 rust 地区能做到吗?

推荐答案

如上所述,test_invariant方法将仅在调试版本中调用.也就是说,参数中的表达式在非调试版本中根本不会求值,这与debug_assert是函数而不是宏的行为不同.这通常是人们想要的,因为生产二进制文件将是一个发布版本,而测试将使用调试.

如果您担心非常慢的代码会使您运行调试版本变得不切实际,您可以根据您是否正在进行测试来创建您自己的宏,该宏是有条件定义的:

macro_rules! test_assert {
    ($($tt: tt)*) => { 
        #[cfg(test)]
        assert!($($tt)*)
    }
}

除了只在测试中执行任何操作外,test_assert!宏的行为与debug_assert!类似.

不过,通常情况下,如果在可能的情况下在测试中显式地执行测试断言,情况会清楚得多.

Rust相关问答推荐

为什么我需要在这个代码示例中使用&

从Rust调用C++虚拟方法即使在成功执行之后也会引发Access违规错误

Tokio_Postgres行上未显示退回特性的生存期,且生命周期 不够长

为什么基于高山Linux的Docker镜像不能在绝对路径下找到要执行的命令?

字段类型为Boxed的 struct 的生存期必须超过static

失真图像图形捕获Api

如何使用reqwest进行异步请求?

Rust wasm 中的 Closure::new 和 Closure::wrap 有什么区别

Windows 上 ndarray-linalg 与 mkl-stats 的链接时间错误

当我编译 Rust 代码时,我是否缺少 AVX512 的目标功能?

如何将 struct 数组放置在另一个 struct 的末尾而不进行内存分段

为什么 `tokio::join!` 宏不需要 Rust 中的 `await` 关键字?

Rust 中 `Option` 的内存开销不是常量

为什么 Rust 编译器在移动不可变值时执行复制?

为什么基于 clap::Parser 读取的大量数字进行计算比硬编码该数字时慢?

深度嵌套枚举的清洁匹配臂

有没有办法隐藏类型定义?

为什么 `ref` 会导致此示例*取消引用*一个字段?

令人困惑的错误消息? (解包运算符)

为什么可以从不可变 struct 的字段中移动?