Python 在pytest中,如何中止夹具拆卸?

Python 在pytest中,如何中止夹具拆卸?,python,pytest,Python,Pytest,我们的pytest环境有很多固定装置(主要是scope='function'和scope='module'),它们执行以下形式的操作: @pytest.yield_fixture(scope='function') def some_fixture(): ... some object initialization ... yield some_object ... teardown ... 我们使用夹具的拆卸阶段(在成品率之后)删除一些专门为测试创建的资源 但是,如果

我们的pytest环境有很多固定装置(主要是
scope='function'
scope='module'
),它们执行以下形式的操作:

@pytest.yield_fixture(scope='function')
def some_fixture():
    ... some object initialization ...
    yield some_object
    ... teardown ...
我们使用夹具的拆卸阶段(在成品率之后)删除一些专门为测试创建的资源

但是,如果测试失败,我不希望执行拆卸,因此我们仍有资源进行进一步调试

例如,这里有一个常见的场景,在我们所有的测试框架中都会重复:

@pytest.yield_fixture(scope='function')
def obj_fixture():
    obj = SomeObj.create()
    yield obj
    obj.delete()

def test_obj_some_field(obj_fixture):
    assert obj_fixture.some_field is True
在这种情况下,如果
assert
中的条件是
True
我希望执行
obj.delete()
。 但是,如果测试失败,我希望pytest跳过
obj.delete()
,以及
产生
之后的任何内容

多谢各位

编辑
我希望在不改变夹具和测试代码的情况下完成该过程,我更喜欢自动过程,而不是在整个测试代码库中进行重构。

拆卸旨在独立于测试是否通过而执行


因此,我建议您编写拆卸代码,使其足够健壮,无论测试通过还是失败都可以执行,或者在测试结束时添加清理,因此,如果前面的产品组合没有失败,或者之前没有发生异常,则可以调用它。设置一个类级别标志以指示通过/失败,并在拆卸时检查。这没有经过测试,但应该给你一个想法:

@pytest.yield_fixture(scope='function')
def obj_fixture():
    obj = SomeObj.create()
    yield obj
    if this.passed:
      obj.delete()

def test_obj_some_field(obj_fixture):
    assert obj_fixture.some_field is True
    this.passed = True
这本书中有一个关于如何做到这一点的例子。基本思想是,您需要在钩子函数中捕获此信息,并将其添加到测试
,该项可在测试
请求
上获得,该项可通过
请求
装置提供给装置/测试

对你来说,它看起来像这样:

#conftest.py
导入pytest
@hookimpl(tryfirst=True,hookwrapper=True)
def pytest_runtest_makereport(项目,调用):
#执行所有其他挂钩以获取报表对象
结果=产量
rep=结果。获取_结果()
#为调用的每个阶段设置一个报告属性,该属性可以
#是“设置”、“呼叫”、“拆卸”
setattr(项目“代表”+代表时间、代表)
#测试对象
导入pytest
@pytest.fixture()
def obj(请求):
obj=‘obj’
产量目标
#安装成功,但测试本身(“调用”)失败
如果request.node.rep_setup.passed和request.node.rep_call.failed:
打印('Don kill obj here')
其他:
打印('kill obj here')
def测试_obj(obj):
断言obj=='obj'
断言为False#强制测试失败
如果您使用
pytest-s
(为了不让pytest捕获fixture的输出),您将看到如下输出

foobar.py::test_obj FAILED dont kill obj here

这表明我们在使用条件的正确分支。

很抱歉不够精确-我的目标是一个自动解决方案,不需要对所有测试和装置进行重构。我编辑了这篇文章。无论如何,谢谢。我们的存储库由数千个看起来有点像原始帖子中的示例的测试组成,我不想重构所有的方法,我正在寻找一个自动解决方案(可能使用pytest钩子,但我不确定这是正确的方向)。我实际上实现了这一点,但不幸的是,这只是我解决问题的一半。我以最初的问题结束,因为我想完全自动化解决方案——也就是说,不要使用
if…else
子句,而只是在一个失败的断言上
yield
之后中止代码。我认为没有办法做到这一点。如果你在很多地方都需要这样做,你可以在“测试成功后运行回调”函数中总结这个行为,然后(在夹具内部)向该函数传递一个进行清理的回调。我会考虑你提出的解决方案,我同意我最初的目标可能是一条死胡同,谢谢!