【发布时间】:2011-11-23 07:14:53
【问题描述】:
背景故事
我正在将QuickCheck 单元测试框架移植到C(请参阅GitHub 的工作代码)。语法将是:
for_all(property, gen1, gen2, gen3 ...);
其中property 是要测试的函数,例如bool is_odd(int)。 gen1、gen2 等是为property 生成输入值的函数。有些生成整数,有些生成字符,有些生成字符串,等等。
for_all 将接受具有任意输入(任意数量的参数,任意类型的参数)的函数。 for_all 将运行生成器,创建测试值以传递给属性函数。例如,属性is_odd 是一个类型为bool f(int) 的函数。 for_all 将使用生成创建 100 个测试用例。如果属性为其中任何一个返回 false,for_all 将打印有问题的测试用例值。否则,for_all 将打印 "SUCCESS"。
因此for_all 应该使用va_list 来访问生成器。一旦我们调用了生成器函数,我们如何将它们传递给属性函数?
示例
如果is_odd 具有bool f(int) 类型,我们将如何实现具有以下语法的函数apply():
apply(is_odd, generated_values);
次要问题
见SO。
我们如何智能地打印失败测试用例的任意值?一个测试用例可能是一个整数,或者两个字符,或者一个字符串,或者以上的某种组合?我们不会提前知道是否使用:
printf("%d %d %d\n", some_int, some_int, some_int);printf("%c\n" a_character);printf("%s%s\n", a_string, a_struct_requiring_its_own_printf_function);
【问题讨论】:
-
我不认为我遵循 - 你应该
a)调用每个生成器一次并立即接收整个生成值集合还是b)在循环中调用每个生成器函数以获得后续值要测试? -
好的,我已经阅读了源代码,所以我知道它实际上是
c)每个生成器为特定的函数参数提供后续值。 -
首先:运行给定的生成器来创建一个测试用例。示例:
testme(int, char, char)需要一个随机整数和两个随机字符。一旦我们弄清楚如何做到这一点,我们将让for_all在一个大循环中运行不止一个,而是 100 个测试用例。 -
对于您的次要问题,您需要生成 args 并将它们布置在您也传递的特殊日志记录函数中,或者通过启动
va_list然后传递 started 列出某种打印或处理函数(您可以使用va_list类型作为函数的参数,允许您使用 vararg 函数进行包装和其他处理)。 -
@peachykeen 是的,我想我必须将 API 更改为
for_all(property, gen1, print1, gen2, print2, ...);才能处理任意复杂的数据类型(想想 RedBlack 树)。
标签: c unit-testing tuples quickcheck