1. Property-Based Testing - QuickCheck,属性、生成器、收缩、不变式与集成的核心概念?
请解释 Property-Based Testing(以 QuickCheck 为代表)的核心概念,包括属性、生成器、收缩、不变式,以及它们如何集成工作?
- 属性(Property)与不变式(Invariant)的定义
- 生成器(Generator)与随机输入生成
- 收缩(Shrinking)机制
Property-Based Testing(PBT)的核心思想是"不再为单个输入写断言,而是描述一个对所有输入都成立的性质(Property),并让框架自动生成大量随机输入来验证该性质"。其核心概念包括:属性(Property)是"对任意输入,程序都应满足的规则",如"任意列表排序后长度不变";生成器(Generator)负责按一定分布产生随机输入(整数、字符串、列表、对象等);收缩(Shrinking)是在发现反例后,自动把导致失败的输入逐步化简为最小的反例,方便定位缺陷;不变式(Invariant)是属性中最重要的形式,描述程序在任何合法输入下都应保持的不变规律。QuickCheck(Haskell 起源)是 PBT 的鼻祖,其思想被广泛移植到各语言。集成方面,PBT 与例式测试互补:例式测试提供具体基准用例,PBT 提供随机广搜,二者结合可兼顾精确性与广泛性。
PBT 的价值在于把"测试某个例子"提升为"测试一类性质",通过随机生成揭示人工难以预见的边界缺陷。学习者应把握"属性是核心、生成器驱动、收缩助定位"这条主线。
// 使用 jqwik(Java)声明一个属性
@Property
boolean sortKeepsLength(@ForAll List<Integer> list) {
List<Integer> sorted = list.stream().sorted().toList();
return sorted.size() == list.size(); // 不变式:排序不改变长度
}