基于堆栈的自动测试用例生成
项目描述
Testmachine是一种新的测试方法。它是一个Python库,旨在测试Python程序,但其核心概念是语言无关的,并且应该很容易移植到其他语言。
它强烈受到Quickcheck和其他类似模糊测试方法的影响,但有一个本质上的变化,即彻底颠覆了该理念,使其变得更为强大。
核心概念是testmachine不生成数据,它生成程序。这基于来自Scalacheck(以及我在hypothesis中将它移植到Python的后续工作)中的有状态测试系统中的想法,但testmachine同样适用于有状态和无状态的系统。
由statemachine生成的程序是由一系列用户提供的规则定义的。这些规则通常分为以下三个类别
生成随机值的功能(如quickcheck中的Arbitrary)
关于值的断言(如quickcheck中的Property)
组合值的规则(这在quickcheck中很难做到)
实际上,这三个都由同一类型内部表示,有时可能会方便地使用这些规则的混合体(例如,同时进行某些断言的操作,或返回随机断言的函数),但总的来说,这种分离是方便的。
您将这些规则定义为Python函数,然后testmachine会尝试找到一组组合,该组合会产生异常。如果找到了,它会尽力最小化它,并将最终输出编译成简单的文本格式,通常可以解释为有效的Python(它是由简单字符串扩展从模式生成的。如果您的值具有有效的Python repr,并且您没有做任何非常不寻常的事情,那么输出将是有效的Python。否则,可能需要一些编辑,但应可独立阅读)。
用法示例
状态
目前,这段代码应被视为相当实验性的。您可以使用它,它可能会正常工作,但我不能保证API的稳定性。它仍然是一个正在进行的工作,因为我正在探索一个新想法。
内部机制
它是如何工作的?
在核心,Testmachine描述了一种可以在具有多个命名值堆栈的机器上执行的程序语言。它生成随机程序,试图找到导致错误的程序。
每个程序是一系列操作。每个操作都可以以任意方式操作堆栈。如果操作抛出异常,则testmachine现在已找到一个错误。
由于其基于堆栈操作的定义,因此很容易最小化程序:程序只是一个操作列表,其中没有显式依赖关系(所有数据依赖都通过堆栈进行),因此您可以从中删除指令,删除任何发现自己处于无效状态(例如,如果堆栈上没有足够值,则所需值不足)的指令,并查看程序是否仍然失败。如果它失败了,您已经缩小了程序。然后我们贪婪地迭代这个过程,直到无法进一步缩小程序。
虽然这并不保证产生全局最小化程序,但在实践中,它通常在生成简短示例程序方面做得非常好。
一旦完成,我们就有一个针对堆栈机的示例程序。但这不是很易读,所以我们要将其编译成更简单的Python输出。
我们通过维护一组具有变量名的阴影堆栈来完成此操作,每个堆栈对应于我们机器中的堆栈。通过跟踪操作中读取和写入的变量,我们将堆栈操作转换为变量读取和写入集。结果是SSA形式的变量读取和赋值序列,这与堆栈程序等效。然后我们进行一些简单的字符串模板,生成看起来像Python程序输出的输出。
测试
此版本的testmachine已经使用Python系列2.6、2.7、3.2、3.3和pypy进行了测试。构建是通过travis检查的。