5

我正在尝试成对测试并想要基于 Python 的成对测试工具。我已经尝试过 AllPairs(http://pypi.python.org/pypi/AllPairs/2.0.1)。当我在一列中给出 10 个条目时,它有错误。目前使用微软 PICT 生成成对组合。

Python中是否有任何工具可以为大型数组生成成对组合?

AllPairs 中的错误如果我给这个

parameters = [ [ "Brand X", "Brand Y","Brand A","Brand B","Brand C","Brand D" ]
             , [ "98", "NT", "2000", "XP"]
             , [ "Internal", "Modem","A","B","C","D","E","F","G","H","I","J","K","L","M" ]
             , [ "Salaried", "Hourly", "Part-Time", "Contr.","AA","BB","CC","DD","EE","FF","GG","HH","II" ]
             , [ 6, 10, 15, 30, 60, 70, 80, 90, 100, 110, 120, 130, 140 ]
             ]

输出是

Brand X count is 16
Brand Y count is 122
Brand A count is 16
Brand B count is 16
Brand C count is 16
Brand D count is 15

为了这

parameters = [ [ "Brand X", "Brand Y","Brand A","Brand B","Brand C","Brand D" ]
             , [ "98", "NT", "2000", "XP"]
             , [ "Internal", "Modem" ]
             , [ "Salaried", "Hourly", "Part-Time", "Contr." ]
             , [ 6, 10, 15, 30, 60 ]
             ]

输出是

Brand X count is 5
Brand Y count is 5
Brand A count is 5
Brand B count is 5
Brand C count is 5
Brand D count is 6

我认为,对于更大的阵列工作是不正确的。

4

4 回答 4

3

这样的事情怎么样?

from itertools import chain, combinations, product

def pairwiseGen(*sequences):
    unseen = set(chain.from_iterable(product(*i) for i in combinations(sequences, 2)))
    for path in product(*sequences):
        common_pairs = set(combinations(path, 2)) & unseen
        if common_pairs:
            yield path
            unseen.difference_update(common_pairs)

用法(使用parameters您在问题中定义的列表):

>>> pairs = list(pairwiseGen(*parameters))
>>> len(pairs)
846

我认为仍有一些优化空间(上面的生成器产生的结果比预期的要多一些),但我认为你会同意它比使用笛卡尔积要短得多

>>> all_possible = list(product(*parameters))
>>> len(all_possible)
60480
于 2012-06-09T05:11:52.483 回答
2

使用allpairspy怎么样?它是AllPairs的一个分支,具有更多功能(可能是错误修复)和文档。调整为您的参数的基本用法示例代码返回 200 个 5 元组:

from allpairspy import AllPairs

parameters = [
    [ "Brand X", "Brand Y","Brand A","Brand B","Brand C","Brand D" ],
    [ "98", "NT", "2000", "XP"],
    [ "Internal", "Modem","A","B","C","D","E","F","G","H","I","J","K","L","M" ],
    [ "Salaried", "Hourly", "Part-Time", "Contr.","AA","BB","CC","DD","EE","FF","GG","HH","II" ],
    [ 6, 10, 15, 30, 60, 70, 80, 90, 100, 110, 120, 130, 140 ]
]

print("PAIRWISE:")
for i, pairs in enumerate(AllPairs(parameters)):
    print("{:2d}: {}".format(i, pairs))

如果您想测试 Python 代码或使用基于 pytest 的测试框架,您可以通过其测试参数化功能将 allpairspy 与 pytest 集成

于 2017-11-20T08:28:55.030 回答
1

TL;DR AllPairs 返回一个有效的成对测试集,即使品牌和 Windows 版本的分布不均匀。

例子

这是您的示例:

Brand : Brand X, Brand Y, Brand A, Brand B, Brand C, Brand D
Version : 98, NT, 2000, XP
Network : Internal, Modem, A, B, C, D, E, F, G, H, I, J, K, L, M
Wage : Salaried, Hourly, Part-Time, Contr., AA, BB, CC, DD, EE, FF, GG, HH, II
Time : 6, 10, 15, 30, 60, 70, 80, 90, 100, 110, 120, 130, 140

有效性:

如果您检查,您会发现 PICT 和 AllPairs 都包含所有 993 个 2 元组。这意味着 PICT 和 AllPairs 都返回有效集合。

上述示例中 2 元组的总数为:

6*4 + 6*15 + 6*13 + 6*13 + 4*15 + 4*13 + 4*13 + 15*13 + 15*13 + 13*13 = 993

表现:

测试用例的典型数量为 O(nm),其中 n 和 m 是两个最大参数。在这种情况下:15*13 = 195 是测试集的绝对最小数量。

AllPairs 返回 200 个 5 元组

PICT 返回 206 个 5 元组

因此 PICT 和 AllPairs 都返回接近测试集的最小数量。

分布

Raj 指出的是 AllPairs 返回一个分布不均的测试集。

品牌:

Brand A : 16
Brand B : 16
Brand C : 16
Brand D : 15
Brand X : 16
Brand Y : 122

版本:

98 : 155
2000 : 15
NT : 16
XP : 15

PICT 返回更均匀分布的测试集

品牌:

Brand A : 26
Brand B : 32
Brand C : 40
Brand D : 35
Brand X : 40
Brand Y : 33

版本:

98 : 48
2000 : 55
NT : 52
XP : 51

解释

Brand 和 Version 的不均匀分布仍然有效的原因是这两个字段的基数最低(6 和 4)。因此,AllPairs 似乎正在填充获得所有 Network 和 Wage 对所需的 5 元Brand YWindows 98

以下是每个字段的基数:

Brand : 6
Version : 4
Network : 15
Wage : 13
Time : 13
于 2016-05-06T22:02:00.130 回答
1

我刚刚围绕 MS pict 实现创建了一个包装器,这可能对您有用。显然具有依赖性,但可以节省重新创建轮子。

import os
import tempfile
import subprocess


def all_pairs(*sequence):
    """
    Calculate the all pairs testing sequence from the Microsoft PICT all pairs application
    that is compiled from: https://github.com/Microsoft/pict

    >>> Type = ['Single', 'Span', 'Stripe', 'Mirror', 'RAID-5']
    >>> Size = [10, 100, 500, 1000, 5000, 10000, 40000]
    >>> Format_method = ['Quick', 'Slow']
    >>> File_system = ['FAT', 'FAT32', 'NTFS']
    >>> Cluster_size = [512, 1024, 2048, 4096, 8192, 16384, 32768, 65536]
    >>> Compression = ['On', 'Off']
    >>> combinations = all_pairs(Type, Size, Format_method, File_system, Cluster_size, Compression)
    >>> assert len(combinations) == 56
    """
    exe = '/opt/pict/bin/pict'
    assert os.path.exists(exe), 'Make sure you have install the PICT executable to: {}'.format(exe)
    assert len(sequence) > 0
    for s in sequence:
        assert isinstance(s, list)
        assert len(s) > 0

    # create input file
    lines = list()
    for i, s in enumerate(sequence):
        seq = ', '.join([str(r) for r in range(len(s))])
        new_line = '{}: {}'.format(i, seq)
        lines.append(new_line)

    with tempfile.NamedTemporaryFile(mode='w') as tmp:
        tmp.write(os.linesep.join(lines))
        tmp.flush()
        result = subprocess.check_output([exe, tmp.name])

    options = list()
    for line in result.split(os.linesep)[1:]:  # skip the header
        if len(line) == 0:
            continue
        indices = [int(i) for i in line.split('\t')]
        options.append([s[i] for s, i in zip(sequence, indices)])
    return options
于 2016-08-17T10:38:05.140 回答