11

我正在使用 pytest 来测试嵌入式系统的 python 模型。要测试的功能因平台而异。(在这种情况下,我使用“平台”来表示嵌入式系统类型,而不是操作系统类型)。

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

/platform1
/platform2
/etc.

pytest /平台1

这很快变得难以支持,因为许多功能跨平台重叠。从那以后,我将测试移到了一个目录中,每个功能区域的测试都分配给了一个文件名(例如 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 行将是一个很大的帮助。

4

2 回答 2

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

请注意,如果您通过标记命令行选项指定平台,如下所示:

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

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

于 2012-06-06T14:34:57.720 回答
6

聚会迟到了,但我刚刚通过向所有未标记的测试添加默认标记解决了类似的问题。

作为对问题的直接回答:您可以始终运行未标记的测试,并仅包含通过-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})"
于 2019-04-30T13:16:06.740 回答