简体   繁体   English

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

[英]How to override a pytest fixture calling the original in pytest 4

I am defining a pytest fixture that to overrides the django_db_setup fixture . 我正在定义一个覆盖django_db_setup fixture的django_db_setup fixture

The change I have sets up additional teardown for safety, as there are integration tests that use this fixture which may spawn processes and cleanup is sometimes required to keep all things from breaking. 为了安全起见,我已经设置了额外的拆卸,因为有使用此夹具的集成测试可能会产生进程并且有时需要进行清理以防止所有事情发生破坏。

This seems reasonable, and is also suggested in pytest docs. 这似乎是合理的,并且也在pytest docs中提出。 However, I don't want to copy paste the same exact logic of django_db_setup since I'm happy with what is already there. 但是,我不想复制粘贴django_db_setup的相同逻辑,因为我对已经存在的内容感到满意。 Running it as a function, however, raises a deprecation warning: 但是,将其作为函数运行会引发弃用警告:

/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.

What would be the recommended way to deal with this situation in pytest 4? 在pytest 4中处理这种情况的推荐方法是什么? Are we encouraged to copy-paste code from fixtures we want to override, or is there another way to "inherit" a fixture, and inject eg custom behavior before as well as after it is called? 我们是否鼓励从我们想要覆盖的灯具中复制粘贴代码,或者是否有另一种“继承”灯具的方法,并调用之前和之后注入自定义行为?

To inject custom behavior before the initial fixture is called you can create separate fixture with this behavior and use it before the initial fixture in parameter list of fixture that overrides previously defined: 要在调用初始夹具之前注入自定义行为,您可以使用此行为创建单独的夹具,并在夹具的参数列表中的初始夹具之前使用它,该夹具覆盖先前定义的:

@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')

There is a simple trick to redefine a fixture with a custom impl. 使用自定义impl重新定义夹具有一个简单的技巧。 Just declare a fixture with the same name and signature in your local test code (I usually do it in the conftest.py in project root). 只需在本地测试代码中声明一个具有相同名称和签名的fixture(我通常在项目根目录中的conftest.py中进行)。 Examples: 例子:

"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')

Notice I have django_db_setup argument in the custom django_db_setup fixture - this ensures the original fixture is called before the custom one. 请注意,我在自定义django_db_setup fixture中有django_db_setup参数 - 这可以确保在自定义夹具之前调用原始夹具。

"Redeclaration" “重新说明”

If you omit the argument, the custom fixture will replace the original one, so it won't be executed: 如果省略参数,自定义夹具将替换原始夹具,因此不会执行:

@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'
    ))

BTW, this is another handy trick to use when you eg want to turn off a fixture that is defined elsewhere. 顺便说一句,这是另一个方便的技巧,当你想要关闭其他地方定义的灯具时。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM