pytest中如何控制测试用例的执行顺序?

2025-03-13 09:22:00
admin
原创
15
摘要:问题描述:我在一个目录中有两个文件。其中一个文件中有一个长时间运行的测试用例,它会生成一些输出。另一个文件中有一个读取该输出的测试用例。如何确保两个测试用例的执行顺序正确?除了以正确的顺序将测试用例放在同一个文件中之外,还有其他选择吗?解决方案 1:一般来说,你可以使用 pytest明确指定的钩子来配置其基本...

问题描述:

我在一个目录中有两个文件。其中一个文件中有一个长时间运行的测试用例,它会生成一些输出。另一个文件中有一个读取该输出的测试用例。

如何确保两个测试用例的执行顺序正确?除了以正确的顺序将测试用例放在同一个文件中之外,还有其他选择吗?


解决方案 1:

一般来说,你可以使用 pytest明确指定的钩子来配置其基本上任何部分的行为。

就您而言,您需要“pytest_collection_modifyitems”钩子,它可以让您重新排序收集的测试。

话虽如此,但测试排序似乎应该更容易——毕竟这是 Python!所以我写了一个用于测试排序的插件:“pytest-ordering”。查看文档或从​​pypi安装。现在我建议使用@pytest.mark.first@pytest.mark.second或其中一个@pytest.mark.order#标记,但我对更有用的 API 有一些想法。欢迎提出建议 :)

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

编辑2order :在pytest-order中,只支持一个标记( ),并且提到的例子将是@pytest.mark.order("first")、、@pytest.mark.order("second")@pytest.mark.order(#)(其中#是任意数字)。

解决方案 2:

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

请小心——评论表明这并不适合所有人。

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

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

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

解决方案 3:

正如@Frank T在接受的答案中所指出的,pytest_collection_modifyitemshook钩子允许修改收集测试的顺序 ( items)。这种方法的优点是不需要任何第三方库。

该答案中已经提供了有关如何按测试类强制执行测试用例执行顺序的完整示例。

但是,在这种情况下,您似乎希望按测试模块(即.py测试所在的文件)强制执行执行顺序。以下修改将允许您这样做:

# conftest.py
def pytest_collection_modifyitems(items):
    """Modifies test items in place to ensure test modules run in a given order."""
    MODULE_ORDER = ["tests.test_b", "tests.test_c", "tests.test_a"]
    module_mapping = {item: item.module.__name__ for item in items}

    sorted_items = items.copy()
    # Iteratively move tests of each module to the end of the test queue
    for module in MODULE_ORDER:
        sorted_items = [it for it in sorted_items if module_mapping[it] != module] + [
            it for it in sorted_items if module_mapping[it] == module
        ]
    items[:] = sorted_items

将上面的代码片段放入其中,conftest.py将默认的字母测试执行顺序test_a-> test_b->替换test_ctest_b-> test_c-> test_a。模块可以位于不同的测试子目录中,模块内的测试顺序保持不变。

解决方案 4:

Pytest 的 Fixtures 可用于对测试进行排序,其方式与对 Fixtures 的创建进行排序的方式类似。虽然这种方式并不常见,但它充分利用了您可能已经掌握的 Fixture 系统知识,不需要单独的软件包,也不太可能被 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-dependspytest-order一旦我用 卸载它们pip uninstall package_name,问题就消失了。看起来它们有副作用

解决方案 6:

纯 pytest 解决方案是使用pytest.mark.parametrize,向其传递要调用的子函数的任意排序列表。在本问题中提出的问题中,您必须从文件(或其中一个文件)导入测试函数。无论哪种方式,您都需要一个__init__.py文件。

这是一个最小的工作示例,不含导入:

tests/
- __init__.py  (empty)
- tests_that_need_ordering.py
- test_run_ordered.py
# tests_that_need_ordering.py
def C():
    assert False

def A():
    assert False

def B():
    pass
# test_run_ordered.py
import pytest

from .tests_that_need_ordering import A, B, C


@pytest.mark.parametrize("func", [C, B, A])
def test_things(func):
    func()

请注意

  • 子函数文件名不以test- 开头或结尾,否则它将被 pytest 直接拾取。同样,如果 pytest 查看,则不会拾取其中的测试名称。

  • 函数定义顺序为 CA B。如果它们是文件test_*中的普通函数test_*,pytest 会按照此顺序调用它们。

  • 精心设计的参数化顺序是CB A。

详细运行的输出-vv表明它们按照 CBA 的故意顺序运行,并且故障按预期报告:

tests/test_run_ordered.py::test_things[C] FAILED
tests/test_run_ordered.py::test_things[B] PASSED
tests/test_run_ordered.py::test_things[A] FAILED

为了方便以后参考,我使用 Python 3.10.13、pytest-7.4.2 执行了此操作

解决方案 7:

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

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

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

将测试依赖项标记为固定装置,并将其作为参数传递给依赖项。

解决方案 8:

主要文件:

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

演示.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

解决方案 9:

函数导入顺序也决定了执行顺序。在下面的用例中,可重用测试被导入到模块中,导入顺序优先于调用顺序。

from livy.reusable_livy_tests import (
    test_delete_livy_session,
    test_create_livy_session,
    test_get_livy_session,
    test_livy_session_started,
    test_computation_of_a_statement,
)

test_create_livy_session
test_get_livy_session
test_livy_session_started
test_computation_of_a_statement
test_delete_livy_session

在上面的示例中,test_delete_livy_session 首先运行,因为它是首先导入的,尽管最后被调用。我今天在 python 版本 3.6.8、pytest 版本 7.0.0 中观察到了这一点。

解决方案 10:

利用pytest-randomly插件中的“--randomly-dont-reorganize”选项或“-p no: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

解决方案 11:

@swimmer 的回答很好。这是完善的代码。

确保测试项目首先运行

# conftest.py
def pytest_collection_modifyitems(items):
    """test items come to first"""
    run_first = ["tests.test_b", "tests.test_c", "tests.test_a"]
    modules = {item: item.module.__name__ for item in items}
    items[:] = sorted(
        items, key=lambda x: run_first.index(modules[x]) if modules[x] in run_first else len(items)
    )

确保测试项目最后运行

# conftest.py
def pytest_collection_modifyitems(items):
    """test items come to last"""
    run_last = ["tests.test_b", "tests.test_c", "tests.test_a"]
    modules = {item: item.module.__name__ for item in items}
    items[:] = sorted(
        items, key=lambda x: run_last.index(modules[x]) if modules[x] in run_last else -1
)
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1590  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1361  
  信创产品在政府采购中的占比分析随着信息技术的飞速发展以及国家对信息安全重视程度的不断提高,信创产业应运而生并迅速崛起。信创,即信息技术应用创新,旨在实现信息技术领域的自主可控,减少对国外技术的依赖,保障国家信息安全。政府采购作为推动信创产业发展的重要力量,其对信创产品的采购占比情况备受关注。这不仅关系到信创产业的发展前...
信创和国产化的区别   18  
  信创,即信息技术应用创新产业,旨在实现信息技术领域的自主可控,摆脱对国外技术的依赖。近年来,国货国用信创发展势头迅猛,在诸多领域取得了显著成果。这一发展趋势对科技创新产生了深远的推动作用,不仅提升了我国在信息技术领域的自主创新能力,还为经济社会的数字化转型提供了坚实支撑。信创推动核心技术突破信创产业的发展促使企业和科研...
信创工作   18  
  信创技术,即信息技术应用创新产业,旨在实现信息技术领域的自主可控与安全可靠。近年来,信创技术发展迅猛,对中小企业产生了深远的影响,带来了诸多不可忽视的价值。在数字化转型的浪潮中,中小企业面临着激烈的市场竞争和复杂多变的环境,信创技术的出现为它们提供了新的发展机遇和支撑。信创技术对中小企业的影响技术架构变革信创技术促使中...
信创国产化   19  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用