#property-testing #properties #quickcheck #testing #fuzz #shrinking

开发工具 qcheck-macros

quickcheck 的宏属性

1 个稳定版本

使用旧的 Rust 2015

1.0.0 2022 年 12 月 4 日

#9#shrinking

Download history 39/week @ 2024-03-14 36/week @ 2024-03-21 49/week @ 2024-03-28 40/week @ 2024-04-04 28/week @ 2024-04-11 34/week @ 2024-04-18 33/week @ 2024-04-25 39/week @ 2024-05-02 28/week @ 2024-05-09 50/week @ 2024-05-16 40/week @ 2024-05-23 49/week @ 2024-05-30 33/week @ 2024-06-06 33/week @ 2024-06-13 38/week @ 2024-06-20 9/week @ 2024-06-27

124 每月下载次数
用于 5 crates

Unlicense OR MIT

8KB
74

quickcheck

QuickCheck 是一种使用随机生成的输入进行属性测试的方法。此crate具有随机生成和缩小整数、浮点数、元组、布尔值、列表、字符串、选项和结果的能力。QuickCheck 所需的只是一个属性函数——然后它会随机生成该函数的输入,并针对每一组输入调用该属性。如果属性失败(无论是由于运行时错误(如索引越界)还是不满足您的属性),则输入将“缩小”以找到更小的反例。

列表和数字的缩小策略使用二分搜索快速覆盖输入空间。

文档

API 已完全文档化: https://docs.rs/qcheck

#[quickcheck] 属性

为了使编写 QuickCheck 测试更容易,#[quickcheck] 属性会将属性函数转换为 #[test] 函数。

要使用 #[quickcheck] 属性,您必须从 quickcheck_macros crate 导入 quickcheck 宏。

#[cfg(test)]
mod tests {
    fn reverse<T: Clone>(xs: &[T]) -> Vec<T> {
        let mut rev = vec!();
        for x in xs {
            rev.insert(0, x.clone())
        }
        rev
    }

    #[quickcheck]
    fn double_reversal_is_identity(xs: Vec<isize>) -> bool {
        xs == reverse(&reverse(&xs))
    }
}

缩小

缩小是 QuickCheck 的关键部分,可以自动简化属性的反例。例如,如果您错误地将反转向量的函数定义为:(对于这个精心设计的例子,我深表歉意)

fn reverse<T: Clone>(xs: &[T]) -> Vec<T> {
    let mut rev = vec![];
    for i in 1..xs.len() {
        rev.insert(0, xs[i].clone())
    }
    rev
}

并添加一个属性来测试以下条件:xs == reverse(reverse(xs))

fn prop(xs: Vec<isize>) -> bool {
    xs == reverse(&reverse(&xs))
}
quickcheck(prop as fn(Vec<isize>) -> bool);

然后不进行缩小,你可能会得到一个反例,如下所示

[quickcheck] TEST FAILED. Arguments: ([-17, 13, -12, 17, -8, -10, 15, -19,
-19, -9, 11, -5, 1, 19, -16, 6])

这看起来相当神秘。但是,启用缩小功能后,你几乎每次都能得到这个反例

[quickcheck] TEST FAILED. Arguments: ([0])

这将使调试变得更加容易。

增加测试数量

另一种方法是让quickcheck运行属性更多次。你可以通过tests()方法或通过QUICKCHECK_TESTS环境变量来做到这一点。这将导致quickcheck运行更长时间。与循环方法不同,这将在有限的时间内完成,这使得它更适合像发布周期这样的需求,需要真正对软件进行压力测试。

生成结构体

在QuickCheck中生成结构体非常简单。以下是一个示例,其中定义了结构体Point

struct Point {
    x: i32,
    y: i32,
}

为了生成一个随机的Point实例,你需要为结构体Point实现Arbitrary特质

use qcheck::{Arbitrary, Gen};

impl Arbitrary for Point {
    fn arbitrary(g: &mut Gen) -> Point {
        Point {
            x: i32::arbitrary(g),
            y: i32::arbitrary(g),
        }
    }
}

许可证

双许可下MIT或UNLICENSE

依赖项

~1.5MB
~35K SLoC