如何使用集合组合作为测试数据

How to use combinations of sets as test data

提问人:nlucaroni 提问时间:8/3/2008 最后编辑:Abdulla Nilamnlucaroni 更新时间:9/13/2017 访问量:11294

问:

我想用一组边缘情况和正常值中的元组测试一个函数。例如,在测试一个函数时,只要给定三个形成有效三角形的长度,就会返回该函数,我会有特定的情况,负数/小数/大数,接近溢出的值等;更重要的是,主要目的是生成这些值的组合,无论是否重复,以获得一组测试数据。true

(inf,0,-1), (5,10,1000), (10,5,5), (0,-1,5), (1000,inf,inf),
...

注意:我实际上知道这个问题的答案,但它可能对其他人有所帮助,对这里的人来说也是一个挑战!--稍后会发布我的答案。

单元 与语言无关 的测试

评论

0赞 Nikos M. 3/6/2015
Abacus github 一个用于 Node.JS、Python、PHP、Actionscript 的组合库(ps 我是作者)

答:

3赞 Mark Harrison 8/3/2008 #1

有趣的问题!

我会通过选择组合来做到这一点,就像 python 中的下面一样。最难的部分可能是第一次通过验证,即,这是一个正确的结果吗?一旦你验证了这一点,那么这就是回归测试的良好基础。if f(1,2,3) returns true

也许最好制作一组你知道全部为真的测试用例(例如,这个三角形案例为 3,4,5),以及一组你知道将全部为错误的测试用例(例如 0,1,inf)。然后,您可以更轻松地验证测试是否正确。

# xpermutations from http://code.activestate.com/recipes/190465
from xpermutations import *

lengths=[-1,0,1,5,10,0,1000,'inf']
for c in xselections(lengths,3):        # or xuniqueselections
    print c
(-1,-1,-1);
(-1,-1,0);
(-1,-1,1);
(-1,-1,5);
(-1,-1,10);
(-1,-1,0);
(-1,-1,1000);
(-1,-1,inf);
(-1,0,-1);
(-1,0,0);
...
18赞 nlucaroni 8/4/2008 #2

当然,尤其是处理大量这些排列/组合时,我绝对可以看到第一遍将是一个问题。

python 中有趣的实现,尽管我基于“算法 515”(见下文)用 C 和 Ocaml 编写了一个不错的实现。他用 Fortran 写了他的,因为当时所有“算法 XX”论文都很常见,嗯,那个程序集或 c。我不得不重写它并做一些小的改进来处理数组而不是数字范围。这个是随机访问的,我仍在努力获得 Knuth 第 4 卷第 2 章中提到的一些不错的实现。我将向读者解释这是如何工作的。虽然如果有人好奇,我不会反对写一些东西。

/** [combination c n p x]
 * get the [x]th lexicographically ordered set of [p] elements in [n]
 * output is in [c], and should be sizeof(int)*[p] */
void combination(int* c,int n,int p, int x){
    int i,r,k = 0;
    for(i=0;i<p-1;i++){
        c[i] = (i != 0) ? c[i-1] : 0;
        do {
            c[i]++;
            r = choose(n-c[i],p-(i+1));
            k = k + r;
        } while(k < x);
        k = k - r;
    }
    c[p-1] = c[p-2] + x - k;
}

~“算法 515:从词典索引生成向量”;Buckles, B. P. 和 Lybanon, M. ACM Transactions on Mathematical Software,第 3 卷,第 2 期,1977 年 6 月。

评论

2赞 Matt K 2/28/2012
该怎么办?那基本上是返回选择吗?choose()n-c[i]p-(i+1)1
0赞 CuppM 5/19/2015
对不起,我没有遵循选择行为。这听起来像是被定义为自我反身的——选择确实选择。你能用更简单的术语告诉我它的作用吗?
1赞 nlucaroni 5/19/2015
“自我反省”是一个不正确的术语。它被称为“递归”,它是计算机科学的基本组成部分。所讨论的“选择”函数是 C(N,K),en.wikipedia.org/wiki/Binomial_coefficient 。
2赞 Andrew Savinykh 6/7/2015
应该注意的是,x 是从 1 开始的,而不是像人们预期的那样从 0 开始。
0赞 Subu Sankara Subramanian 10/30/2015
甚至 c 数组似乎也指将集合元素称为从 1 开始而不是从 0 开始。考虑到我们增加了 c[i],它永远不能引用第 0 个元素。还是我错过了什么?还是 OP 的意思是用 -1 初始化 c[i] 并说 choose(n-c[i]-1,...)?
2赞 Jon Limjap 8/16/2008 #3

我认为您可以使用行测试属性(在 MbUnit 及更高版本的 NUnit 中可用)来做到这一点,您可以在其中指定多个集来填充一个单元测试。

0赞 not-bob 9/17/2008 #4

虽然可以创建大量测试数据并查看会发生什么,但尝试最小化正在使用的数据会更有效。

从典型的 QA 角度来看,您可能希望识别不同的输入分类。为每个分类生成一组输入值,并确定适当的输出。

下面是输入值类的示例

  • 具有小数的有效三角形,例如(10 亿、2、十亿、20 亿)
  • 具有大数的有效三角形,例如 (0.000001, 0.00002, 0.00003)
  • “几乎”平坦的有效钝角三角形,例如 (10, 10, 19.9999)
  • “几乎”平坦的有效锐角三角形,例如 (10, 10, 0000001)
  • 至少有一个负值的无效三角形
  • 两条边之和等于第三条边的无效三角形
  • 两条边之和大于第三条边的无效三角形
  • 非数字输入值

...

一旦您对此函数的输入分类列表感到满意,就可以创建实际的测试数据。测试每个项目的所有排列可能会有所帮助。(例如(2,3,4)、(2,4,3)、(3,2,4)、(3,4,2)、(4,2,3)、(4,3,2))通常,您会发现遗漏了一些分类(例如,inf 作为输入参数的概念)。

一段时间的随机数据也可能有所帮助,它可以在代码中发现奇怪的错误,但通常效率不高。

更有可能的是,此函数在应用其他规则的某些特定上下文中使用。(例如,只有整数值或值必须以 0.01 为增量等)这些参数添加到输入参数的分类列表中。

4赞 Bite code 10/4/2008 #5

使用全新的 Python 2.6,您有一个带有 itertools 模块的标准解决方案,该模块返回可迭代对象的笛卡尔乘积:

import itertools

print list(itertools.product([1,2,3], [4,5,6]))
   [(1, 4), (1, 5), (1, 6),
   (2, 4), (2, 5), (2, 6),
   (3, 4), (3, 5), (3, 6)]

您可以提供一个 “repeat” 参数来执行具有可迭代对象和自身的产品:

print list(itertools.product([1,2], repeat=3))
[(1, 1, 1), (1, 1, 2), (1, 2, 1), (1, 2, 2),
(2, 1, 1), (2, 1, 2), (2, 2, 1), (2, 2, 2)]

您还可以使用组合进行调整:

print list(itertools.combinations('123', 2))
[('1', '2'), ('1', '3'), ('2', '3')]

如果顺序很重要,则有排列:

print list(itertools.permutations([1,2,3,4], 2))
[(1, 2), (1, 3), (1, 4),
   (2, 1), (2, 3), (2, 4),
   (3, 1), (3, 2), (3, 4),
   (4, 1), (4, 2), (4, 3)]

当然,所有这些很酷的东西并不完全是做同样的事情,但你可以以某种方式使用它们来解决你的问题。

请记住,您可以使用 list()、tuple() 和 set() 将元组或列表转换为集合,反之亦然。