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-dependency
、pytest-depends
、pytest-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)