py.test 在自定义 funcargs 中使用 Monkeypatch

发布于 2024-11-07 12:20:27 字数 1105 浏览 4 评论 0原文

我使用 py.test 并且非常喜欢 funcarg 方法将对象注入到测试函数中。 在我的测试中,我需要使用模拟对象,因为我有很多外部依赖项。我使用 Monkeypatch 将某些属性替换为模拟对象。

我遇到的问题是,我经常会进行一堆使用特定 funcarg 的测试,并且总是需要修补相同的属性。到目前为止,我替换了每个测试函数中的属性。

有没有办法在我的 funcarg 函数中使用 Monkeypatch,并从各个测试中删除这些重复的代码?

import sys
import pytest
from mock import Mock


#----------------------------------------------------------------------
def pytest_funcarg__api(request):
    """"""
    api = myclass()
    #do some initialisation...
    return api


#----------------------------------------------------------------------
def test_bla1(monkeypatch, api):
    """"""
    monkeypatch.setattr(api,"get_external_stuff",Mock())
    monkeypatch.setattr(api,"morestuff",Mock())

    api.do_something1()
    assert not api.a

#----------------------------------------------------------------------
def test_bla2(monkeypatch, api):
    """"""
    monkeypatch.setattr(api,"get_external_stuff",Mock())
    monkeypatch.setattr(api,"morestuff",Mock())

    api.do_something2()
    assert api.b


if __name__=='__main__':
    pytest.main(args=["-v",sys.argv[0]])

I use py.test and really like the funcarg approach to inject objects into test functions.
In my testing I need to work with Mock objects, as I have a lot external dependencies. I use monkeypatch to replace certain attributes with the mock objects.

The problem I have is, that I will often end up with a bunch of tests that will use a certain funcarg and always require the same attributes patched. So far I replace the attributes in every test function.

Is there a way to use monkeypatch in my funcarg functions, and remove this duplicated code from the individual tests?

import sys
import pytest
from mock import Mock


#----------------------------------------------------------------------
def pytest_funcarg__api(request):
    """"""
    api = myclass()
    #do some initialisation...
    return api


#----------------------------------------------------------------------
def test_bla1(monkeypatch, api):
    """"""
    monkeypatch.setattr(api,"get_external_stuff",Mock())
    monkeypatch.setattr(api,"morestuff",Mock())

    api.do_something1()
    assert not api.a

#----------------------------------------------------------------------
def test_bla2(monkeypatch, api):
    """"""
    monkeypatch.setattr(api,"get_external_stuff",Mock())
    monkeypatch.setattr(api,"morestuff",Mock())

    api.do_something2()
    assert api.b


if __name__=='__main__':
    pytest.main(args=["-v",sys.argv[0]])

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

余生一个溪 2024-11-14 12:20:27

您可以使用记录的 getfuncargvalue 函数在内部使用来自另一个函数参数工厂的函数参数:

def pytest_funcarg__api(request):
    api = myclass()
    #do some initialisation...
    mp = request.getfuncargvalue("monkeypatch")
    mp.setattr(api,"get_external_stuff", Mock())
    mp.setattr(api,"morestuff", Mock())
    return api

You can use the documented getfuncargvalue function to internally use a function argument from another function argument's factory:

def pytest_funcarg__api(request):
    api = myclass()
    #do some initialisation...
    mp = request.getfuncargvalue("monkeypatch")
    mp.setattr(api,"get_external_stuff", Mock())
    mp.setattr(api,"morestuff", Mock())
    return api
十年不长 2024-11-14 12:20:27

这应该可行:

def pytest_funcarg__api(request):
    """"""
    api = myclass()
    #do some initialisation...
    mp_plugin = request.config.pluginmanager.getplugin("monkeypatch")
    monkeypatch = mp_plugin.pytest_funcarg__monkeypatch(request)
    monkeypatch.setattr(api,"get_external_stuff",Mock())
    monkeypatch.setattr(api,"morestuff",Mock())
    return api

这里的技巧有两个:

  1. 我们使用 config.pluginmanager 获取 monkeypatch 插件。
  2. 我们通过使用我们自己的请求对象调用其 pytest_funcarg__monkeypatch() funcarg 接口来欺骗 monkeypatch 插件,使其认为它是由 py.test 的依赖注入代码调用的。

This should work:

def pytest_funcarg__api(request):
    """"""
    api = myclass()
    #do some initialisation...
    mp_plugin = request.config.pluginmanager.getplugin("monkeypatch")
    monkeypatch = mp_plugin.pytest_funcarg__monkeypatch(request)
    monkeypatch.setattr(api,"get_external_stuff",Mock())
    monkeypatch.setattr(api,"morestuff",Mock())
    return api

The trick here is two-fold:

  1. We get the monkeypatch plugin using config.pluginmanager.
  2. We fool the monkeypatch plugin into thinking its called by py.test's dependency injection code, by calling its pytest_funcarg__monkeypatch() funcarg-interface with our very own request object.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文