pytest_runtest_teardown 是否要求跳过测试而 pytest_runtest_setup 不是?

Is pytest_runtest_teardown called for skipped tests while pytest_runtest_setup is not?

我有一个实现以下挂钩的插件:

def pytest_runtest_setup(item):
    item.config.bla = Bla()

def pytest_runtest_teardown(item):
    item.config.bla.do_bla()
    item.config.bla = None

一切正常,直到一些测试开始抛出 AttributeError: 'NoneType' object has no attribute 'do_bla',实际上,item.config.blaNone

这发生在我标记为

的测试中
@pytest.mark.skip(reason='bla bla')
def test_bla():
    pass

我试过 ipdb-ing 设置挂钩 - 但它没有被调用,而拆卸是。跳过测试时不调用设置而拆卸测试有意义吗?

我可以用 try, except 结束我的拆解,但我想验证根本原因...

问题似乎是 pytest_runtest_setup 钩子是由 pytest 本身的几个组件实现的,其中一个是 skipping 模块(_pytest/skipping.py)。
该实现执行如下操作:

@hookimpl(tryfirst=True)
def pytest_runtest_setup(item):
    ...
    for skip_info in item.iter_markers(name="skip"):
        item._store[skipped_by_mark_key] = True
        if "reason" in skip_info.kwargs:
            skip(skip_info.kwargs["reason"])
        elif skip_info.args:
            skip(skip_info.args[0])
        else:
            skip("unconditional skip")

例如如果它找到 skip 标记,它会引发 Skipped() (这基本上是 skip 所做的一切),只有在执行任何预测试和测试挂钩之后才会被捕获。

我不知道这是否是故意的,但你显然必须预料到这种行为(在你的情况下你可以很容易地通过捕捉 AttributeError 来做到这一点)。