pytest中的测试用例执行顺序

Posted

技术标签:

【中文标题】pytest中的测试用例执行顺序【英文标题】:Test case execution order in pytest 【发布时间】:2013-07-08 10:19:02 【问题描述】:

我正在使用 pytest。我在一个目录中有两个文件。在其中一个文件中,有一个长时间运行的测试用例会生成一些输出。在另一个文件中有一个读取该输出的测试用例。如何确保两个测试用例的正确执行顺序?除了将测试用例按正确的顺序放在同一个文件中之外,还有其他选择吗?

【问题讨论】:

一般来说,让测试用例相互依赖并不是一个好主意。如果您需要在 2 个测试用例中使用相同的数据,为什么不将其添加到 setup 部分? 我不想将它添加到设置部分,因为它大约需要 15-20 分钟。 嗯,有什么办法可以模拟出来吗?如果没有,那么您可能需要明确链接这两个测试(或将它们设为一项大测试) 共享或环境设置代码进入 setUpClass 方法,它将运行一次,在任何测试运行之前。或者,您可以将延迟初始化模式代码写入 setup 方法。甚至写——initialized=False def test_mytest1: if initialized: somelongfunction() initialized=True 宁可使用框架。考虑这样一种可能性,如果您需要订购测试,它们不再是单元测试,您需要考虑一个新的脚手架工作水平来简化这一点。 这里值得指出的是,在现实世界中测试事物的领域中,例如循环中的硬件装备,有时您需要控制事物的顺序,因为您需要协调现实世界的状态在纯软件测试中可能没有等价物。 【参考方案1】:

一般来说,您可以使用 pytest 的 well-specified hooks 配置基本上任何部分的行为。

在您的情况下,您需要“pytest_collection_modifyitems”钩子,它可以让您重新排序收集的测试。

也就是说,您的测试排序似乎应该更容易——毕竟这是 Python!所以我写了一个用于订购测试的插件:"pytest-ordering"。查看docs 或从pypi 安装它。现在我建议使用@pytest.mark.first@pytest.mark.second,或者@pytest.mark.order# 标记之一,但我对更有用的API 有一些想法。欢迎提出建议:)

编辑:pytest-ordering 目前似乎已被放弃,您也可以查看pytest-order(作者原始项目的一个分支)。

Edit2:在 pytest-order 中,仅支持一个标记 (order),并且提到的示例将显示为 @pytest.mark.order("first")@pytest.mark.order("second")@pytest.mark.order(#)(其中 # 为任何数字)。

【讨论】:

嘿。感谢您创建此插件。您可以对其进行修改,使其仅提取尾随数字作为订单。例如,如果我说 @pytest.mark.custom1 ,那么 1 应该是顺序。这将有很大帮助! 我可以试试。我认为 v0.2 的这种行为带有“顺序”标记,而不是任意标记。你能把它写成 pytest-ordering 的 github 页面上的功能请求吗? github.com/ftobia/pytest-ordering 钩子链接应该转到:pytest.org/latest/writing_plugins.html#well-specified-hooks @meowsqueak 你推断出为什么订单会改变吗? pytest-ordering 插件目前似乎已被放弃。它的一个积极维护的 fork 已创建名为 pytest-order 并且可能应该被使用。 @FrankT您可以修改您的答案以指示应该使用 pytest-order 吗?在 Google 上搜索“pytest 订单测试”(或类似搜索)的人可能会遇到这篇文章,并被当前状态的答案误导。【参考方案2】:

也许您可以考虑使用dependency pytest 插件,您可以在其中轻松设置测试依赖项。

小心 - cmets 认为这并不适合所有人。

@pytest.mark.dependency()
def test_long():
    pass

@pytest.mark.dependency(depends=['test_long'])
def test_short():
    pass

这种方式test_short 只会在test_long 成功并且强制执行顺序时才会执行。

【讨论】:

以上不适用于我的订单排序。例如:如果您翻转订单。即长期依赖于短期。在这种情况下,将跳过 long。 这个答案使用了pytest插件pytest-dependency 测试位于两个不同的模块中,正如github.com/RKrahl/pytest-dependency/issues/3 中指出的那样,仍然不可能有一个测试依赖于另一个模块中的另一个测试 这不适用于 pytest-dependency 0.5.1(我刚刚尝试过)。如果尚未达到,pytest-depedency 将简单地跳过测试,它不会订购测试。 我即将否决这个答案,因为这要么是依赖 0.5.1 中的错误,要么是排序功能不再属于 pytest 依赖的范围。另见github.com/RKrahl/pytest-dependency/issues/20【参考方案3】:

还有一个插件pytest-ordering 似乎符合你的要求。

【讨论】:

Frank T. 的回答已经提到了这个插件,并且是在这个回答之前 3 年发布的。 呃,但他没有提到名字。这就是为什么我可能完全错过了这一点。 现在也提到了这个名字 :-)【参考方案4】:

Pytest 的固定装置可用于以与创建固定装置类似的方式对测试进行排序。虽然这是非常规的,但它利用了您可能已经拥有的夹具系统知识,它不需要单独的包并且不太可能被 pytest 插件更改。

@pytest.fixture(scope='session')
def test_A():
    pass

@pytest.mark.usefixtures('test_A')
def test_B():
    pass

如果有多个依赖于它的测试,则该范围会阻止对 test_A 的多次调用。

【讨论】:

虽然这段代码可以回答问题,但最好解释一下如何解决问题,并提供代码作为示例或参考。仅代码的答案可能会令人困惑且缺乏上下文。【参考方案5】:

重要的是要记住,在尝试修复 pytest 排序“问题”时,按照指定的顺序运行测试似乎是 pytest 的默认行为。

事实证明,由于其中一个包 - pytest-dependencypytest-dependspytest-order,我的测试没有按顺序进行。一旦我用pip uninstall package_name 卸载了它们,问题就消失了。好像有副作用

【讨论】:

【参考方案6】:

Pytest 默认情况下,它随机执行步骤。所以使用这个选项按顺序执行。

安装方式:

pip install pytest-order

测试方法如下:

import pytest

@pytest.mark.order(1)
def test_foo():
    assert True

@pytest.mark.order(2)
def test_bar():
    assert True

【讨论】:

【参考方案7】:

main.py:

import functools
import pytest
from demo import test_foo,test_hi

def check_depends(depends):
    try:
        for dep in depends:
            dep()
    except Exception as e:
        return dep
    else:
        return True

def pytest_depend(depends):
    def pytest_depend_decorator(func):
        stat = check_depends(depends)
        if stat is True:
            return func
        else:
            return pytest.mark.skip(True, reason="%s[skip] --> %s[Failed]" % (func.__name__, stat.__name__))(func)
    return pytest_depend_decorator


@pytest_depend([test_foo,test_hi])
def test_bar():
    pass

@pytest_depend([test_foo,test_hi])
def test_bar2():
    pass

demo.py:

def test_hi():
    pass
def test_foo():
    assert False

平台 linux -- Python 3.5.2、pytest-3.8.2、py-1.6.0、pluggy-0.7.1 -- /usr/bin/python3

pytest -vrsx ./plugin.py

【讨论】:

我不确定我是否会推荐使用它。它将为每个 test_bar 运行 test_foo 和 test_hi,而不是运行一次。此外,如果在测试期间调用了 test_foo 或 test_hi(作为它自己的测试),那么您也不会知道。【参考方案8】:

利用 '--randomly-dont-reorganize' 选项或 '-p no:randomly'pytest-randomly 中提供> 插件,这只会按照你在模块中提到的顺序运行你的测试。

模块:

import pytest

def test_three():
    assert True

def test_four():
    assert True

def test_two():
    assert True

def test_one():
    assert True

执行:

(tmp.w95BqE188N) rkalaiselvan@dev-rkalaiselvan:~/$ py.test --randomly-dont-reorganize test_dumm.py
======================================================================== test session starts ========================================================================
platform linux2 -- Python 2.7.12, pytest-3.10.1, py-1.5.4, pluggy-0.7.1 -- /tmp/tmp.w95BqE188N/bin/python2
cachedir: .pytest_cache
Using --randomly-seed=1566829391
rootdir: /home/rkalaiselvan, inifile: pytest.ini
plugins: randomly-1.2.3, timeout-1.3.1, cov-2.6.0, mock-1.10.0, ordering-0.6
collected 4 items

test_dumm.py::test_three PASSED
test_dumm.py::test_four PASSED
test_dumm.py::test_two PASSED
test_dumm.py::test_one PASSED

(tmp.w95BqE188N) rkalaiselvan@dev-rkalaiselvan:~/$ py.test -p no:randomly test_dumm.py
======================================================================== test session starts ========================================================================
platform linux2 -- Python 2.7.12, pytest-3.10.1, py-1.5.4, pluggy-0.7.1 -- /tmp/tmp.w95BqE188N/bin/python2
cachedir: .pytest_cache
Using --randomly-seed=1566829391
rootdir: /home/rkalaiselvan, inifile: pytest.ini
plugins: randomly-1.2.3, timeout-1.3.1, cov-2.6.0, mock-1.10.0, ordering-0.6
collected 4 items

test_dumm.py::test_three PASSED
test_dumm.py::test_four PASSED
test_dumm.py::test_two PASSED
test_dumm.py::test_one PASSED

【讨论】:

按照指定的顺序运行测试似乎是 pytest 的默认值 @Hemil,您能通过文档链接验证吗?【参考方案9】:

对我来说,修复测试执行顺序的最简单方法是将它们用作固定装置,按照设计顺序执行。

@pytest.fixture()
def test_a():
    print("running test a first")
    pass

def test_b(test_a):
    print("running test b after test a")
    pass

将测试依赖标记为fixture,并将其作为参数传递给依赖项。

【讨论】:

【参考方案10】:

确保您已安装 pytest-ordering 软件包。 要确认转到 Pycharm 设置>>项目解释器>>并查找 pytest-ordering : 如果它不可用,请安装它。 Pycharm设置>>项目解释器>>点击+按钮并搜索pytest-ordering安装它。 瞧!!一定会成功的。

【讨论】:

OP 没有提到 PyCharm

以上是关于pytest中的测试用例执行顺序的主要内容,如果未能解决你的问题,请参考以下文章

pytest文档58-随机执行测试用例(pytest-random-order)

『德不孤』Pytest框架 — 4.pytest.ini文件和用例执行的顺序

接口自动化之pytest——用例设计原则及执行顺序

15-pytest-自定义用例执行顺序

python接口自动化-pytest-用例执行顺序

46-pytest-分布式插件pytest-xdist使用