4 个版本 (稳定)
2.0.0 | 2023年8月27日 |
---|---|
1.0.1 | 2023年3月9日 |
1.0.0 | 2023年3月8日 |
0.1.0 | 2023年3月8日 |
#5 在 #ord
每月下载量 30 次
33KB
404 行
Reltester
Relation tester 是一个用于自动检查 [Partial]Eq
、[Partial]Ord
、Hash
和 [DoubleEnded|Fused]Iterator
特性实现的测试工具。它在与 quickcheck
或其他基于属性的测试框架一起使用时非常有用。
访问 文档!
动机
想象一下,你有一个类型 Foo
,它有自定义实现的 PartialEq
、Eq
、PartialOrd
或 Ord
。这里的“自定义”指的是手工编写,而不是继承。Rust 编译器本身无法验证这些实现的正确性,因此必须由你,程序员,来维护关于你所实现的特定 二元关系 的一些不变性。例如,如果你为 Foo
实现 PartialEq
,你必须保证 foo1 == foo2
意味着 foo2 == foo1
(对称性)。
其他特性如 Hash
和 Iterator
也要求遵守几个不变性——其中一些是非常直观的,而 其他 则不是。在实现 std::iter
系列特性的代码库中,引入不完美的实现是非常常见的,这可能导致诸如 ^1^3 等错误。
想法是,当你手动在代码库中实现这些特性之一时,你可以将这些不变性保存在脑海中,并在测试套件中添加 Reltester 检查,从而有更高的信心保证你的实现是正确的。
如何使用
-
编写一些测试用例,生成您希望测试的类型随机值。您可以通过手动或使用类似
quickcheck
和proptest
的 crate 来实现。 -
根据您的类型实现的特质,调用相应的检查器。
reltester::eq
用于Eq
;reltester::ord
用于Ord
;reltester::partial_eq
用于PartialEq
;reltester::partial_ord
用于PartialOrd
;reltester::hash
用于Hash
;reltester::iterator
用于Iterator
;reltester::fused_iterator
用于FusedIterator
;reltester::double_ended_iterator
用于DoubleEndedIterator
一些这些函数接受多个(两个或三个)相同类型的值。这是因为测试某些不变量可能需要三个值。
有关更多信息,请参阅文档。如果无法满足主函数的类型界限,则 reltester::invariants
模块可用于更细粒度的检查。
示例
f32
(《PartialEq》,PartialOrd
;
use reltester;
use quickcheck_macros::quickcheck;
#[quickcheck]
fn test_f32(a: f32, b: f32, c: f32) -> bool {
// Let's check if `f32` implements `PartialEq` and `PartialOrd` correctly
// (spoiler: it does).
reltester::partial_eq(&a, &b, &c).is_ok()
&& reltester::partial_ord(&a, &b, &c).is_ok()
}
u32
(《Hash
use reltester;
use quickcheck_macros::quickcheck;
#[quickcheck]
fn test_u32(a: u32, b: u32) -> bool {
// Unlike `f32`, `u32` implements both `Eq` and `Hash`, which allows us to
// test `Hash` invariants.
reltester::hash(&a, &b).is_ok()
}
Vec<u32>
(《DoubleEndedIterator
use reltester;
use quickcheck_macros::quickcheck;
#[quickcheck]
fn test_vec_u32(nums: Vec<u32>) -> bool {
// `Iterator` is implied and checked by both `DoubleEndedIterator` and
// `FusedIterator`.
reltester::double_ended_iterator(nums.iter()).is_ok()
&& reltester::fused_iterator(nums.iter()).is_ok()
}
合法
Reltester 在 MIT 许可证下可用。
外部参考和脚注
依赖关系
~0.5–1MB
~23K SLoC