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

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

【问题讨论】:

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

标签: python pytest


【解决方案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
  • @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
        猜你喜欢
        • 1970-01-01
        • 2014-05-15
        • 1970-01-01
        • 2022-09-24
        • 1970-01-01
        • 1970-01-01
        • 2018-04-23
        • 2020-06-04
        • 1970-01-01
        相关资源
        最近更新 更多