1 个不稳定版本
0.1.0 | 2024年7月15日 |
---|
#428 在 测试
111 每月下载量
49KB
699 行
一个带有更强大的assert!()
宏的Rust crate
One Assert
TL;DR
当你可以用assert!(a == b)
(或assert!(a != b)
、assert!(a > b)
等)获得相同输出时,为什么还要有单独的宏,比如assert_eq
和assert_ne
(以及assert_gt
等)?这个crate提供了一个单一的assert!宏,在失败时提供更详细的输出。
简介
Rust的标准库提供了assert
、assert_eq
和assert_ne
宏。然而,这些宏存在一些不便之处,例如没有为其他不等式提供专门化,比如为>=
等提供assert_ge
,或者名称只有一两个字母不同(assert_eq
、assert_ne
、assert_ge
、assert_gt
等),因此容易在视觉上混淆。
不添加更多宏的主要原因是可以用assert!(a >= b)
很好地表示它们,因此没有必要为每种使用情况都使用单独的宏。
但这引发了一个问题:为什么我们最初要有assert_eq
和assert_ne
呢?
实际原因:assert_eq!(a, b)
的输出比assert!(a == b)
更好
let x = 1;
let msg = catch_panic!({ assert!(x == 2); });
assert_eq!(msg, "assertion failed: x == 2");
let msg = catch_panic!({ assert_eq!(x, 2); });
assert_eq!(msg, "assertion `left == right` failed
left: 1
right: 2"
);
如您所见,assert_eq
能够提供关于各个值的具体信息。但是:这并不一定是必须的。Rust有卫生和过程宏,因此我们可以让assert!(a == b)
与assert_eq!(a, b)
具有相同的工作方式
let x = 1;
let msg = catch_panic!({ one_assert::assert!(x == 2); });
assert_eq!(msg, "assertion `x == 2` failed
left: 1
right: 2"
);
现在我们可以将此扩展到我们想要的任何数量的运算符
let x = 1;
let msg = catch_panic!({ one_assert::assert!(x > 2); });
assert_eq!(msg, "assertion `x > 2` failed
left: 1
right: 2"
);
示例
let x = 1;
let msg = catch_panic!({ one_assert::assert!(x > 2); });
assert_eq!(msg, "assertion `x > 2` failed
left: 1
right: 2"
);
let msg = catch_panic!({ one_assert::assert!(x != 1, "x ({}) should not be 1", x); });
assert_eq!(msg, "assertion `x != 1` failed: x (1) should not be 1
left: 1
right: 1"
);
let s = "Hello World";
let msg = catch_panic!({ one_assert::assert!(s.starts_with("hello")); });
assert_eq!(msg, r#"assertion `s.starts_with("hello")` failed
self: "Hello World"
arg 0: "hello""#
);
局限性
- 几个组件需要实现
Debug
- 该宏将打印表达式认为有用的任何部分,并进行调试打印。这意味着这些部分需要实现
Debug
。 - 打印为任何给定表达式类型的部分可能会发生变化,因此建议仅在几乎所有的代码都实现了
Debug
的情况下使用此功能。
- 该宏将打印表达式认为有用的任何部分,并进行调试打印。这意味着这些部分需要实现
Debug
打印即使在断言通过的情况下也会发生- 因为这个宏打印的不仅仅是
==或
!=
比较的两边,它必须处理在表达式评估过程中某些值被移动的事实。这意味着必须提前打印这些值。 - 后果:不要在性能关键代码中使用此宏。
- 然而,需要注意的是,表达式及其每个部分只被评估一次。
- (尽管值得注意的是,像
&&
这样的快速失败运算符通常只会评估左侧并停止,但与此宏一起,它将始终评估两侧)
- (尽管值得注意的是,像
- 因为这个宏打印的不仅仅是
依赖关系
~0.6–1.1MB
~18K SLoC