【问题标题】:How to override a pytest fixture calling the original in pytest 4如何在 pytest 4 中覆盖调用原始设备的 pytest 夹具
【发布时间】:2019-05-16 08:01:19
【问题描述】:

我正在定义一个 pytest 夹具来覆盖 the django_db_setup fixture

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

这似乎是合理的,并且在 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 中处理这种情况的推荐方法是什么?我们是否鼓励我们从我们想要覆盖的固定装置中复制粘贴代码,或者是否有另一种方法来“继承”固定装置,并注入例如自定义行为在调用它之前和之后? p>

【问题讨论】:

    标签: python pytest fixtures pytest-django


    【解决方案1】:

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

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

    【讨论】:

    • 谢谢,我想这就是我要找的。我将尝试这个并报告回来,但文档似乎支持声明顺序很重要:docs.pytest.org/en/latest/…
    【解决方案2】:

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

    “继承”

    # 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 参数 - 这可确保在自定义夹具之前调用原始夹具。

    “重新声明”

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

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

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

    【讨论】:

    • 但是如何在调用原始django_db_setup 之后的 之前执行操作?
    • 似乎夹具参数的顺序现在影响了执行顺序(至少对于相同的范围),所以另一个答案似乎是正确的;忽略我以前的cmets。
    猜你喜欢
    • 2023-03-11
    • 2020-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-23
    • 2014-08-21
    相关资源
    最近更新 更多