Python 如何在 py.test 运行中多次重复每个测试?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21764473/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 23:33:18  来源:igfitidea点击:

How can I repeat each test multiple times in a py.test run?

pythonpytest

提问by Martin Del Vecchio

I want to run each selected py.test item an arbitrary number of times, sequentially.
I don't see any standard py.test mechanism for doing this.

我想按任意次数运行每个选定的 py.test 项目。
我没有看到任何用于执行此操作的标准 py.test 机制。

I attempted to do this in the pytest_collection_modifyitems()hook. I modified the list of items passed in, to specify each item more than once. The first execution of a test item works as expected, but that seems to cause some problems for my code.

我试图在pytest_collection_modifyitems()钩子中做到这一点。我修改了传入的项目列表,以多次指定每个项目。测试项的第一次执行按预期工作,但这似乎给我的代码带来了一些问题。

Further, I would prefer to have a unique test item object for each run, as I use id (item) as a key in various reporting code. Unfortunately, I can't find any py.test code to duplicate a test item, copy.copy()doesn't work, and copy.deepcopy()gets an exception.

此外,我希望每次运行都有一个唯一的测试项对象,因为我在各种报告代码中使用 id (item) 作为键。不幸的是,我找不到任何 py.test 代码来复制测试项,copy.copy()不起作用,并copy.deepcopy()出现异常。

Can anybody suggest a strategy for executing a test multiple times?

有人可以建议多次执行测试的策略吗?

采纳答案by Frank T

In order to run each test a number of times, we will programmatically parameterize each test as the tests are being generated.

为了多次运行每个测试,我们将在生成测试时以编程方式参数化每个测试。

First, let's add the parser option (include the following in one of your conftest.py's):

首先,让我们添加解析器选项(在其中一个 conftest.py 中包含以下内容):

def pytest_addoption(parser):
    parser.addoption('--repeat', action='store',
        help='Number of times to repeat each test')

Now we add a "pytest_generate_tests" hook. Here is where the magic happens.

现在我们添加一个“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))

Running without the repeat flag:

在没有重复标志的情况下运行:

(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 ===========================

Running with the repeat flag:

使用重复标志运行:

(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 ===========================

Further reading:

进一步阅读:

回答by Frank T

One possible strategy is parameterizing the test in question, but not explicitly using the parameter.

一种可能的策略是参数化有问题的测试,但不明确使用参数。

For example:

例如:

@pytest.mark.parametrize('execution_number', range(5))
def run_multiple_times(execution_number):
    assert True

The above test should run five times.

上面的测试应该运行五次。

Check out the parametrization documentation: https://pytest.org/latest/parametrize.html

查看参数化文档:https: //pytest.org/latest/parametrize.html

回答by Martin Del Vecchio

Based on Frank T's suggestion, I found a very simple solution in the pytest_generate_tests() callout:

根据 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()

Now executing "py.test --count 5" causes each test to be executed five times in the test session.

现在执行“py.test --count 5”会导致每个测试在测试会话中执行五次。

And it requires no changes to any of our existing tests.

它不需要对我们现有的任何测试进行更改。

Thanks Frank T!

谢谢弗兰克 T!

回答by jsj

The pytest module pytest-repeatexists for this purpose, and I recommend using modules where possible, rather than re-implementing their functionality yourself.

pytest 模块pytest-repeat为此目的而存在,我建议尽可能使用模块,而不是自己重新实现它们的功能。

To use it simply add pytest-repeatto your requirements.txtor pip install pytest-repeat, then execute your tests with --count n.

要使用它,只需将它添加pytest-repeat到您的requirements.txtor 中pip install pytest-repeat,然后使用--count n.

回答by user7610

Based on what I've seen here, and given that I already do some filtering of tests in pytest_collection_modifyitems, my method of choice is the following. In conftest.py

根据我在这里看到的内容,并且鉴于我已经对 中的测试进行了一些过滤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