pytest是否支持“默认”标记?

时间:2012-06-06 00:29:15

标签: python pytest

我正在使用pytest来测试嵌入式系统的python模型。要测试的功能因平台而异。 (我在这个上下文中使用'platform'来表示嵌入式系统类型,而不是OS类型。)

组织我的测试最直接的方法是根据平台类型将它们分配到目录。

/platform1
/platform2
/etc.

pytest / platform1

由于许多功能在不同平台上重叠,因此很快就难以支持。我已经将我的测试移动到一个目录中,每个功能区域的测试分配给一个文件名(例如test_functionalityA.py)。 然后我使用pytest标记来指示文件中的哪些测试适用于给定的平台。

@pytest.mark.all_platforms
def test_some_functionalityA1():
    ...

@pytest.mark.platform1
@pytest.mark.platform2
def test_some_functionlityA2():
    ...

虽然我喜欢让'conftest'自动检测平台类型并且只运行相应的测试,但我已经辞职,指定在命令行上运行哪些测试。

pytest -m“(platform1或all_platforms)”

问题:(最后!)

是否有办法简化操作并默认运行pytest运行所有未标记的测试,另外所有测试都通过命令行上的'-m'传递?

例如: pytest -m“platform1”

会运行标记为@ pytest.mark.platform1的测试以及所有标记为@ pytest.mark.all_platforms的测试,甚至所有测试都没有@ pytest.mark吗?

鉴于大量的共享功能,能够删除@ pytest.mark.all_platforms行将是一个很大的帮助。

2 个答案:

答案 0 :(得分:9)

让我们解决完整的问题。我认为你可以把一个conftest.py文件和你的测试放在一起,它会注意跳过所有不匹配的测试(非标记的测试总是匹配,因此永远不会被跳过)。我在这里使用 sys.platform ,但我相信您有不同的方法来计算您的平台价值。

# content of conftest.py
#
import sys
import pytest

ALL = set("osx linux2 win32".split())

def pytest_runtest_setup(item):
    if isinstance(item, item.Function):
        plat = sys.platform
        if not hasattr(item.obj, plat):
            if ALL.intersection(set(item.obj.__dict__)):
                pytest.skip("cannot run on platform %s" %(plat))

有了这个,你可以像这样标记你的测试::

# content of test_plat.py

import pytest

@pytest.mark.osx
def test_if_apple_is_evil():
    pass

@pytest.mark.linux2
def test_if_linux_works():
    pass

@pytest.mark.win32
def test_if_win32_crashes():
    pass

def test_runs_everywhere_yay():
    pass

如果你用::

运行
$ py.test -rs

然后你可以运行它,并且会看到至少两个测试跳过并且总是 至少执行了一次测试::

然后你将看到两个测试跳过和两个执行的测试按预期::

$ py.test -rs # this option reports skip reasons
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.2.5.dev1
collecting ... collected 4 items

test_plat.py s.s.
========================= short test summary info ==========================
SKIP [2] /home/hpk/tmp/doc-exec-222/conftest.py:12: cannot run on platform linux2

=================== 2 passed, 2 skipped in 0.01 seconds ====================

请注意,如果您通过marker-command line选项指定平台,例如::

$ py.test -m linux2
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.2.5.dev1
collecting ... collected 4 items

test_plat.py .

=================== 3 tests deselected by "-m 'linux2'" ====================
================== 1 passed, 3 deselected in 0.01 seconds ==================

然后不会运行未标记的测试。因此,这是一种将运行限制为特定测试的方法。

答案 1 :(得分:0)

晚了聚会,但是我只是通过向所有未标记的测试中添加默认标记来解决了类似的问题。

作为对该问题的直接答案:您可以始终运行未标记的测试,并且仅通过-m选项指定的方式包含标记的测试,方法是将以下内容添加到conftest.py

def pytest_collection_modifyitems(items, config):
    # add `always_run` marker to all unmarked items
    for item in items:
        if not any(item.iter_markers()):
            item.add_marker("always_run")
    # Ensure the `always_run` marker is always selected for
    markexpr = config.getoption("markexpr", 'False')
    config.option.markexpr = f"always_run or ({markexpr})"