如何覆盖在 pytest 4 中调用原始的 pytest fixture

How to override a pytest fixture calling the original in pytest 4

我正在定义一个覆盖 the django_db_setup fixture.

的 pytest 装置

为了安全起见,我所做的更改设置了额外的拆解,因为有使用此固定装置的集成测试,它可能会产生进程,并且有时需要进行清理以防止所有东西损坏。

这似乎是合理的,并且在 pytest 文档中也有建议。但是,我不想复制粘贴与 django_db_setup 完全相同的逻辑,因为我对已经存在的内容感到满意。 运行 但是,它作为一个函数会引发弃用警告:

/usr/local/lib/python3.6/dist-packages/_pytest/fixtures.py:799:

 RemovedInPytest4Warning: Fixture "django_db_setup" called directly.
 Fixtures are not meant to be called directly, are created automatically
 when test functions request them as parameters. See
 https://docs.pytest.org/en/latest/fixture.html for more information.

在 pytest 4 中处理这种情况的推荐方法是什么?我们是否鼓励从我们想要覆盖的固定装置中复制粘贴代码,或者是否有另一种方法 "inherit" 固定装置,并在 之前和之后 注入例如自定义行为叫什么?

有一个简单的技巧可以使用自定义实现重新定义夹具。只需在本地测试代码中声明一个具有相同名称和签名的夹具(我通常在项目根目录的 conftest.py 中这样做)。示例:

"Inheritance"

# conftest.py

import pytest


@pytest.fixture(scope='session')
def django_db_setup(
    request,
    django_db_setup,
    django_test_environment,
    django_db_blocker,
    django_db_use_migrations,
    django_db_keepdb,
    django_db_createdb,
    django_db_modify_db_settings,
):
    # do custom stuff here
    print('my custom django_db_setup executing')

注意我在自定义 django_db_setup 夹具中有 django_db_setup 参数 - 这确保在自定义夹具之前调用原始夹具。

"Redeclaration"

如果省略参数,自定义夹具将替换原来的夹具,因此不会执行:

@pytest.fixture(scope='session')
def django_db_setup(
    request,
    django_test_environment,
    django_db_blocker,
    django_db_use_migrations,
    django_db_keepdb,
    django_db_createdb,
    django_db_modify_db_settings,
):
    print((
        'my custom django_db_setup executing - '
        'original django_db_setup will not run at all'
    ))

顺便说一句,这是另一个方便的技巧。想要关闭在别处定义的灯具。

要在调用初始夹具之前注入自定义行为,您可以使用此行为创建单独的夹具,并在夹具的参数列表中的初始夹具之前使用它来覆盖先前定义的:

@pytest.fixture(scope='session')
def inject_before():
    print('inject_before')

@pytest.fixture(scope='session')
def django_db_setup(inject_before, django_db_setup):
    print('inject_after')