【问题标题】:Does pytest support "default" markers?pytest 是否支持“默认”标记?
【发布时间】:2019-04-30 21:16:06
【问题描述】:

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

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

/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' 自动检测平台类型并只运行适当的测试,但我已经让自己指定在命令行上运行哪些测试。 p>

pytest -m "(platform1 or all_platforms)"

问题:(终于!)

有没有办法简化事情并让 pytest 默认运行所有未标记的测试,以及在命令行上通过“-m”传递的所有测试?

例如: pytest -m "platform1"

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

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

【问题讨论】:

    标签: python pytest


    【解决方案1】:

    让我们解决全部问题。我认为您可以将 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 ==================
    

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

    【讨论】:

    • 工作就像一个魅力。谢谢霍尔格。
    • 让其他人知道,此答案的来源来自pytest.org/latest/example/…,您可以在那里找到更多示例。
    【解决方案2】:

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

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

    【讨论】:

    • 好的解决方案,例如如果您有一些测试标记为慢,并且您只想默认运行快速的测试。
    猜你喜欢
    • 2010-11-03
    • 2011-07-22
    • 1970-01-01
    • 1970-01-01
    • 2017-07-28
    • 2023-02-07
    • 2012-12-01
    • 1970-01-01
    相关资源
    最近更新 更多