首页 > 解决方案 > 在存在错误的情况下完成 pytest 夹具

问题描述

我有一个测试台设置,我大量使用固定装置为我定义的测试提供资源和“要测试的项目”。这很棒,它允许我的测试函数包含尽可能少的代码。

但是,我发现自己在最终确定方面与 pytest 进行了很多斗争。

在 pytest 中,fixture 终结器可以通过以下形式的生成器方便地描述:

@pytest.fixture
def a_fixture():
    #some setup code
    resource = setup_resource()

    yield resource

    #finalizer code here
    close_resource(resource)

经常,我发现自己希望我能做到这一点:

@pytest.fixture
def a_fixture():
    #some setup code
    resource = setup_resource()

    try:
        yield resource
    except ValueError as e:
        #handle errors in finalization code
        handle_error(resource)

    #finalizer code here
    close_resource()

一些示例用例:

  1. 我的许多测试都是在连接到主机 PC 的硬件上测试功能。发生错误时,我希望完成代码从设备收集更多信息并记录下来。
  2. 如果发生特定类型的错误,我想更改执行的最终代码。例如,测试导致被测设备崩溃,尝试运行最终代码只会浪费时间。

我为此向 pytest 项目提出了一张票,他们告诉我这个决定是设计使然,对我来说最好的选择是创建一个自定义报告挂钩。

我发现固定装置的概念非常有用和强大。我还发现终结器代码无法被告知错误是非常有限的。自定义报告挂钩对我不起作用,因为终结器代码与其源夹具链接太紧密。

那么现在问题来了:如果不将异常传播到夹具中是设计使然,那么您如何提供有条件的资源最终确定?

标签: python-3.xpytest

解决方案


我刚刚开始pytest并遇到了根据测试结果最终确定夹具的需要。

作为参考,我认为是您提出的票?我从那里的响应中获得了一些灵感,最终得到了一个相当简单的解决方案:

@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
    """
    attach each test's TestReport to the test Item so fixtures can
    decide how to finalize based on the test result.

    fixtures can access the TestReport from the `request` fixture at
    `request.node.test_report`.
    """
    test_report = (yield).get_result()
    if test_report.when == "call":
        item.test_report = test_report

现在,在我的夹具中,我可以检查报告:

@pytest.fixture
def my_fixture(request):

    # setup ...

    yield

    if request.node.test_report.outcome == "passed":
        # passing-only finalization ...

钩子将影响所有测试,但它应该是一个相当良性的添加。

我没有使用静态类型检查,但如果你是,你可能需要使用pytest's "stash" 功能而不是直接分配给item/ node


推荐阅读