我希望按顺序运行每个选定的py.test项目任意次数 我没有看到任何标准的py.test机制。
我尝试在pytest_collection_modifyitems()
挂钩中执行此操作。我修改了传入的项目列表,以多次指定每个项目。测试项的第一次执行按预期工作,但这似乎导致我的代码出现一些问题。
此外,我希望每次运行都有一个唯一的测试项目对象,因为我使用id(item)作为各种报告代码中的一个键。不幸的是,我找不到任何py.test代码来复制测试项,copy.copy()
不起作用,copy.deepcopy()
获得异常。
有人可以建议多次执行测试的策略吗?
答案 0 :(得分:36)
为此目的存在pytest模块pytest-repeat,我建议尽可能使用模块,而不是自己重新实现它们的功能。
要使用它,只需将pytest-repeat
添加到requirements.txt
或pip install pytest-repeat
,然后使用--count n
执行测试。
答案 1 :(得分:32)
一种可能的策略是参数化相关测试,但不明确使用参数。
例如:
@pytest.mark.parametrize('execution_number', range(5))
def run_multiple_times(execution_number):
assert True
上述测试应该运行五次。
答案 2 :(得分:12)
为了多次运行每个测试,我们将在生成测试时以编程方式参数化每个测试。
首先,让我们添加解析器选项(在其中一个conftest.py中包含以下内容):
def pytest_addoption(parser):
parser.addoption('--repeat', action='store',
help='Number of times to repeat each test')
现在我们添加一个“pytest_generate_tests”钩子。这就是魔术发生的地方。
def pytest_generate_tests(metafunc):
if metafunc.config.option.repeat is not None:
count = int(metafunc.config.option.repeat)
# We're going to duplicate these tests by parametrizing them,
# which requires that each test has a fixture to accept the parameter.
# We can add a new fixture like so:
metafunc.fixturenames.append('tmp_ct')
# Now we parametrize. This is what happens when we do e.g.,
# @pytest.mark.parametrize('tmp_ct', range(count))
# def test_foo(): pass
metafunc.parametrize('tmp_ct', range(count))
没有重复标记运行:
(env) $ py.test test.py -vv
============================= test session starts ==============================
platform darwin -- Python 2.7.5 -- py-1.4.20 -- pytest-2.5.2 -- env/bin/python
collected 2 items
test.py:4: test_1 PASSED
test.py:8: test_2 PASSED
=========================== 2 passed in 0.01 seconds ===========================
使用repeat标志运行:
(env) $ py.test test.py -vv --repeat 3
============================= test session starts ==============================
platform darwin -- Python 2.7.5 -- py-1.4.20 -- pytest-2.5.2 -- env/bin/python
collected 6 items
test.py:4: test_1[0] PASSED
test.py:4: test_1[1] PASSED
test.py:4: test_1[2] PASSED
test.py:8: test_2[0] PASSED
test.py:8: test_2[1] PASSED
test.py:8: test_2[2] PASSED
=========================== 6 passed in 0.01 seconds ===========================
进一步阅读:
答案 3 :(得分:7)
根据Frank T的建议,我在pytest_generate_tests()标注中找到了一个非常简单的解决方案:
parser.addoption ('--count', default=1, type='int', metavar='count', help='Run each test the specified number of times')
def pytest_generate_tests (metafunc):
for i in range (metafunc.config.option.count):
metafunc.addcall()
现在执行“py.test --count 5”会导致每个测试在测试会话中执行五次。
它不需要对我们现有的任何测试进行任何更改。
谢谢Frank T!
答案 4 :(得分:1)
根据我在这里看到的内容,并且鉴于我已经在pytest_collection_modifyitems
中进行了一些测试过滤,因此我的选择方法如下。在conftest.py
def pytest_addoption(parser):
parser.addoption ('--count', default=1, type='int', metavar='count', help='Run each test the specified number of times')
def pytest_collection_modifyitems(session, config, items):
count = config.option.count
items[:] = items * count # add each test multiple times
答案 5 :(得分:0)
pytest-repeat
(最受欢迎的答案)不适用于unittest
类测试,而pytest-flakefinder
却可以:
pip install pytest-flakefinder
pytest --flake-finder --flake-runs=5 tests...
在找到test-flakefinder
之前,我写了一篇类似脚本的小技巧。您可以找到它here。该脚本的顶部包含有关如何运行该脚本的说明。