Pytest - 除非你声明一个选项/标志,否则如何跳过测试?

时间:2017-11-29 18:35:27

标签: python unit-testing pytest

我有一些单元测试,但是我正在寻找一种标记某些特定单元测试的方法,以便在调用测试时声明选项时跳过它们。

实施例: 如果我拨打pytest test_reports.py,我就不希望运行几个特定的​​单元测试。

但是如果我打电话给pytest -<something> test_reports,那么我希望我的所有测试都能运行。

我查看了@pytest.mark.skipif(condition)标签,但无法弄明白,所以不确定我是否在正确的轨道上。这里的任何指导都会很棒!

5 个答案:

答案 0 :(得分:6)

我们在conftest.py中使用带有addoption的标记

<强>测试用例:

@pytest.mark.no_cmd
def test_skip_if_no_command_line():
    assert True

<强> conftest.py: 功能

def pytest_addoption(parser):
    parser.addoption("--no_cmd", action="store_true",
                     help="run the tests only in case of that command line (marked with marker @no_cmd)")
功能

def pytest_runtest_setup(item):
    if 'no_cmd' in item.keywords and not item.config.getoption("--no_cmd"):
        pytest.skip("need --no_cmd option to run this test")

pytest电话:

    py.test test_the_marker 
    -> test will be skipped

   py.test test_the_marker --no_cmd
   -> test will run

答案 1 :(得分:4)

pytest documentation提供了一个很好的示例,说明如何跳过默认情况下标记为“慢”的测试,并且仅使用--runslow选项运行它们:

# conftest.py

import pytest


def pytest_addoption(parser):
    parser.addoption(
        "--runslow", action="store_true", default=False, help="run slow tests"
    )


def pytest_configure(config):
    config.addinivalue_line("markers", "slow: mark test as slow to run")


def pytest_collection_modifyitems(config, items):
    if config.getoption("--runslow"):
        # --runslow given in cli: do not skip slow tests
        return
    skip_slow = pytest.mark.skip(reason="need --runslow option to run")
    for item in items:
        if "slow" in item.keywords:
            item.add_marker(skip_slow)

我们现在可以通过以下方式标记测试:

# test_module.py
from time import sleep

import pytest


def test_func_fast():
    sleep(0.1)


@pytest.mark.slow
def test_func_slow():
    sleep(10)

总是执行测试test_func_fast(例如,调用pytest)。但是,“慢速”功能test_func_slow仅在调用pytest --runslow时执行。

答案 2 :(得分:2)

有两种方法可以做到:

第一种方法是使用@pytest.mark装饰器标记函数,并使用-m选项单独运行/跳过标记函数。

@pytest.mark.anytag
def test_calc_add():
    assert True

@pytest.mark.anytag
def test_calc_multiply():
    assert True

def test_calc_divide():
    assert True

py.test -m anytag test_script.py运行脚本只会运行前两个函数。

或者以py.test -m "not anytag" test_script.py运行只运行第三个函数并跳过前两个函数。

这里'anytag'是标签的名称。它可以是任何东西。!

第二种方法是使用-k选项在名称中使用公共子字符串运行函数。

def test_calc_add():
    assert True

def test_calc_multiply():
    assert True

def test_divide():
    assert True

py.test -k calc test_script.py运行脚本将运行这些功能并跳过最后一个。

请注意,'calc'是函数名中的公共子字符串,其名称中包含'calc'的任何其他函数也会运行。

答案 3 :(得分:1)

遵循方法suggested in the pytest docs,因此the answer of @Manu_CJ,当然是通往这里的路。

我只想展示如何调整它以轻松定义多个选项:

canonical example given by the pytest docs 很好地突出了如何通过命令行选项添加单个标记。但是,调整它以添加多个标记可能并不容易,因为三个钩子 pytest_addoptionpytest_configurepytest_collection_modifyitems 都需要被调用以允许添加通过命令行选项的单个标记。

这是您调整规范示例的一种方式,如果您有多个标记,例如 'flag1''flag2' 等,您希望能够通过命令行选项添加:

# content of conftest.py
 
import pytest

# Create a dict of markers.
# The key is used as option, so --{key} will run all tests marked with key.
# The value must be a dict that specifies:
# 1. 'help': the command line help text
# 2. 'marker-descr': a description of the marker
# 3. 'skip-reason': displayed reason whenever a test with this marker is skipped.
optional_markers = {
    "fag1": {"help": "<Command line help text for flag1...>",
             "marker-descr": "<Description of the marker...>",
             "skip-reason": "Test only runs with the --{} option."},
    "fag2": {"help": "<Command line help text for flag2...>",
             "marker-descr": "<Description of the marker...>",
             "skip-reason": "Test only runs with the --{} option."},
    # add further markers here
}


def pytest_addoption(parser):
    for marker, info in optional_markers.items():
        parser.addoption("--{}".format(marker), action="store_true",
                         default=False, help=info['help'])


def pytest_configure(config):
    for marker, info in optional_markers.items():
        config.addinivalue_line("markers",
                                "{}: {}".format(marker, info['marker-descr'])


def pytest_collection_modifyitems(config, items):
    for marker, info in optional_markers.items():
        if config.getoption("--{}".format(marker)):
            return
        skip_test = pytest.mark.skip(
            reason=info['skip-reason'].format(marker)
        )
        for item in items:
            if marker in item.keywords:
                item.add_marker(skip_test)

现在您可以在测试模块中使用 optional_markers 中定义的标记:

# content of test_module.py

import pytest


@pytest.mark.flag1
def test_some_func():
    pass


@pytest.mark.flag2
def test_other_func():
    pass

答案 4 :(得分:0)

我认为你要找的是sys.argv。有关详细信息,请访问:http://www.pythonforbeginners.com/system/python-sys-argv

还有另一种更简单(但可以说是无聊)的方法How do I run Python script using arguments in windows command line