How to use combinations of sets as test data
我想用一组边缘情况和正常值的元组测试一个函数。 例如,当测试一个函数,只要给定三个形成有效三角形的长度,它就会返回true,我会遇到一些特殊情况,负数/小数/大数,接近溢出的值,等等。 此外,主要目的是生成这些值的组合(重复或不重复),以获取一组测试数据。
1 2
| (inf,0,-1), (5,10,1000), (10,5,5), (0,-1,5), (1000,inf,inf),
... |
As a note: I actually know the answer to this, but it might be helpful for others, and a challenge for people here! --will post my answer later on.
绝对地,尤其是处理许多这样的排列/组合时,我绝对可以看到第一遍是一个问题。
有趣的python实现,尽管我基于" Algorithm 515"在C和Ocaml中编写了一个不错的代码(请参见下文)。他在Fortran中编写了他的著作,因为那是所有" Algorithm XX"论文(当时是汇编语言或c语言)的普遍用法。我不得不重新编写它,并做了一些小的改进以使用数组而不是数字范围。这是一个随机访问,我仍在努力获得Knuth第4卷第2卷中提到的方法的一些不错的实现。我将向读者解释这种方法的工作原理。虽然如果有人好奇,我不会反对写些东西。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| /** [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在数学软件上的交易,第1卷。 3,第2号,1977年6月。
使用全新的Python 2.6,您可以使用带有itertools模块的标准解决方案,该模块返回iterables的笛卡尔积:
1 2 3 4 5 6
| 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"参数来使用迭代器及其自身来执行产品:
1 2 3
| 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)] |
您还可以通过组合来调整某些内容:
1 2
| print list(itertools.combinations('123', 2))
[('1', '2'), ('1', '3'), ('2', '3')] |
如果顺序很重要,则可以进行排列:
1 2 3 4 5
| 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()将元组或列表转换为集合,反之亦然。
有趣的问题!
我可以通过选择组合来做到这一点,类似于python中的以下内容。最难的部分可能是首次通过验证,即if f(1,2,3) returns true,这是正确的结果吗?一旦您验证了这一点,那么这就是进行回归测试的良好基础。
最好使一组您知道都为真的测试用例(例如,对于这个三角情况为3,4,5),以及一组您知道都为假的测试用例(例如,0,1) ,inf)。然后,您可以更轻松地验证测试是否正确。
1 2 3 4 5 6
| # 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 2 3 4 5 6 7 8 9 10 11
| (-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);
... |
我认为您可以使用行测试属性(在MbUnit和NUnit的更高版本中提供)来执行此操作,您可以在其中指定几组来填充一个单元测试。
尽管可以创建大量测试数据并查看会发生什么,但是尝试最小化正在使用的数据更为有效。
从典型的质量检查角度来看,您将希望确定输入的不同分类。为每个分类生成一组输入值,并确定适当的输出。
这是输入值类别的样本
-
数量较少的有效三角形,例如(10亿,20亿,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为增量等)将这些添加到输入参数的分类列表中。
|