pytest:以 DRY 方式参数化设备 [英] pytest: parameterize fixtures in a DRY way

查看:27
本文介绍了pytest:以 DRY 方式参数化设备的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 Pytest 固定装置,我正在寻找一种将设置覆盖传递给我的应用程序固定装置的方法,这样我就可以测试不同的设置而无需定义不同的固定装置.

Using Pytest fixtures, I'm looking for a way to pass settings overrides to my application fixtures, so I can test different settings without having to define different fixtures.

我在为 Flask 创建测试时使用的一种常见模式是初始化应用程序和数据库,如下所示.请注意,db 固定装置将 app 固定装置硬编码为参数.

I'm using a common pattern when creating tests for Flask is to initialize the app and the database like follows. Notice that the db fixture hard-codes the app fixture as an argument.

from myapp import create_app

@pytest.fixture
def app():
    settings_override = {}  # By setting values here, I can pass in different Flask config variables
    app = create_app(settings_override)
    return app

@pytest.fixture
def db(app):
    do_something_to_create_the_database(app)  # app needed for context
    yield db

然后,许多测试可能会使用上面定义的夹具,例如.

And then, a number of tests might use the fixtures defined above such as.

def test_my_application_1(db, app):
  ...

def test_my_application_2(db, app):
  ...

假设我想用不同的设置初始化应用程序装置,假设我可以将这些设置传递到上面定义的 create_app() 函数中.在每个测试的基础上,如何附加 appdb 固定装置,以便我可以将设置覆盖传递给 app 固定装置?有没有办法可以在测试用例级别参数化夹具,以便我可以将不同的设置传递给夹具?

Let's say I want to initialize the app fixture with different settings, and let's say I can pass those settings into the create_app() function defined above. On a per-test basis, how can a attach the app and db fixtures such that I can pass in settings overrides to the app fixture? Is there a way I can parameterize the fixture at a test case level so I can pass in different settings to the fixture?

# for this test, I want to pass the BAZ=True setting to the app fixture. 
def test_my_application_1(db, app):
  ...

# for this test, I want to pass FOO=BAR setting to the app fixture
def test_my_application_2(db, app):
  ...

感谢您提供的任何建议.

I appreciate any advice you have to offer.

更新:来自@mrbean-bremen 的解决方案

感谢@MrBean Bremen 提供了优雅的解决方案.通过使用 hasattr 稍作修改,我能够扩展解决方案以接受参数覆盖或接受默认值.

Thanks to @MrBean Bremen for the elegant solution. With a slight modification using the hasattr, I was able to extend the solution to accept parameter overrides or to accept a default.

@pytest.fixture(scope='function')
def app(request):
    settings_override = {
        'SQLALCHEMY_DATABASE_URI': "sqlite:///:memory:",
    }
    params = request.param if hasattr(request, 'param') else {}
    return create_app({**settings_override, **params})


@pytest.fixture(scope='function')
def db(app):
    with app.app_context():
       ....


def test_without_params(db, app):
    ...


@pytest.mark.parametrize("app", [{'DEBUG': True}], indirect=True)
def test_with_overrides(db, app):
    ...


推荐答案

您可以尝试将设置作为字典参数传递给装置,如下所示:

You could try to pass the settings as a dictionary parameter to the fixture, something like this:

import pytest
from myapp import create_app

@pytest.fixture
def app(request):
    settings_override = {
        'SQLALCHEMY_DATABASE_URI': "sqlite:///:memory:",
    }
    params = request.param if hasattr(request, 'param') else {}
    return create_app({**settings_override, **params})

@pytest.fixture
def db(app):
    do_something_to_create_the_database(app)
    yield db

def test_my_application_no_override_params(db, app):
    ...

@pytest.mark.parametrize("app", [{'BAZ': True}], indirect=True)
def test_my_application_1(db, app):
    ...

@pytest.mark.parametrize("app", [{'FOO': 'BAR'}], indirect=True)
def test_my_application_2(db, app):
    ...

request 对象允许夹具访问请求测试上下文,并可用作任何夹具中的参数.
pytest.mark.parametrize 装饰器中的 indirect=True 参数将参数传递给 request 的可选 param 属性code> 对象,因此这实质上是对装置本身进行参数化.

The request object gives the fixture access to the requesting test context and can be used as an argument in any fixture.
The indirect=True argument in the pytest.mark.parametrize decorator passes the parameter to the optional param attribute of the request object, so this essentially parametrizes the fixture itself.

更新:
我添加了@JoeJ 提出的有用的补充(hasattr 的使用),这使得在没有附加参数的情况下使用测试成为可能.

UPDATE:
I added the helpful addition (usage of hasattr) as proposed by @JoeJ, which makes it possible to use a test without the additional parameters.

这篇关于pytest:以 DRY 方式参数化设备的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆