Python pytest中参数笛卡尔积的参数化测试
只是想知道,有没有(更)优雅的笛卡尔积参数化方法?到目前为止,我发现:Python pytest中参数笛卡尔积的参数化测试,python,pytest,Python,Pytest,只是想知道,有没有(更)优雅的笛卡尔积参数化方法?到目前为止,我发现: numbers = [1,2,3,4,5] vowels = ['a','e','i','o','u'] consonants = ['x','y','z'] cartesian = [elem for elem in itertools.product(*[numbers,vowels,consonants])] @pytest.fixture(params=cartesian) def somepara
numbers = [1,2,3,4,5]
vowels = ['a','e','i','o','u']
consonants = ['x','y','z']
cartesian = [elem for elem in itertools.product(*[numbers,vowels,consonants])]
@pytest.fixture(params=cartesian)
def someparams(request):
return request.param
def test_something(someparams):
pass
至少我想在fixture函数中封装数字、元音、辅音和笛卡尔。我可以想出两种方法。一个使用参数化夹具,一个参数化测试功能。这取决于你觉得哪一个更优雅 以下是参数化的测试功能:
import itertools
import pytest
numbers = [1,2,3,4,5]
vowels = ['a','e','i','o','u']
consonants = ['x','y','z']
@pytest.mark.parametrize('number,vowel,consonant',
itertools.product(numbers, vowels, consonants)
)
def test(number, vowel, consonant):
pass
值得注意的是,parametrize decorator的第二个参数可以是iterable,而不仅仅是list
以下是通过参数化每个装置来实现的方法:
import pytest
numbers = [1,2,3,4,5]
vowels = ['a','e','i','o','u']
consonants = ['x','y','z']
@pytest.fixture(params=numbers)
def number(request):
return request.param
@pytest.fixture(params=vowels)
def vowel(request):
return request.param
@pytest.fixture(params=consonants)
def consonant(request):
return request.param
def test(number, vowel, consonant):
pass
你的直觉是正确的。通过参数化多个装置中的每个装置,pytest负责创建所有出现的排列
测试输出是相同的。下面是一个示例(我使用-vv选项运行了py.test):
您可以应用多个
参数化参数,在这种情况下,它们将生成所有参数的乘积:
import pytest
numbers = [1,2,3,4,5]
vowels = ['a','e','i','o','u']
consonants = ['x','y','z']
@pytest.mark.parametrize('number', numbers)
@pytest.mark.parametrize('vowel', vowels)
@pytest.mark.parametrize('consonant', consonants)
def test(number, vowel, consonant):
pass
我认为除了一个优雅的解决方案之外,你还应该考虑每个选项所花费的时间和你必须维护的代码量。
可能的解决方案
使用itertools(由Frank T提供)一次参数化
使用3个固定装置(由Frank T提供)
使用参数化
3次(由Bruno Oliveira提供)
使用1个夹具和itertools(问题中提供)
解决方案1
解决方案2
解决方案3
解决方案4
当谈到优雅时,我认为<强>解决方案3 <强>是最好的选择,因为它的代码维护较少,不需要导入代码>迭代器。在这之后,解决方案1是最佳选择,因为您不需要将fixture写为解决方案4,而解决方案2解决方案4可能优于解决方案2,因为它需要更少的代码来维护
在性能方面,我使用numbers=list(范围(100))
运行每个解决方案,并得到以下结果:
| Solution | Time |
| Solution 1 | 3.91s |
| Solution 2 | 3.59s |
| Solution 3 | 3.54s |
| Solution 4 | 3.09s |
这在Python2中应该可以正常工作。你犯了什么错误?pytest 5.X不再支持Python2.7和Python3.4,但是那些执行“pip install pytest”的Python版本的用户将获得最后一个兼容版本4.6.X。
@pytest.mark.parametrize('number, vowel, consonant',
itertools.product(numbers, vowels, consonants))
def test(number, vowel, consonant):
pass
@pytest.fixture(params=numbers)
def number(request): return request.param
@pytest.fixture(params=vowels)
def vowel(request): return request.param
@pytest.fixture(params=consonants)
def consonant(request): return request.param
def test(number, vowel, consonant):
pass
@pytest.mark.parametrize('number', numbers)
@pytest.mark.parametrize('vowel', vowels)
@pytest.mark.parametrize('consonant', consonants)
def test(number, vowel, consonant):
pass
@pytest.fixture(params=cartesian)
def someparams(request):
return request.param
def test_something(someparams):
pass
| Solution | Time |
| Solution 1 | 3.91s |
| Solution 2 | 3.59s |
| Solution 3 | 3.54s |
| Solution 4 | 3.09s |