我正在尝试测试依赖于第三方的代码,并希望使用 Monkeypatch 来复制我期望请求返回的内容。这是我拥有的代码的最小示例。
import requests
def get_urls(*urls):
results = []
for url in urls:
results.append(requests.get(url).text)
Run Code Online (Sandbox Code Playgroud)
对于我的测试,我有如下内容:
from my_package import get_urls
def test_get_urls():
urls = ("https://example.com/a", "https://example.com/b", "https://example.com/c")
assert len(get_urls(urls)) == 3
Run Code Online (Sandbox Code Playgroud)
如何对每个 using 调用进行猴子requests.get
补丁monkeypatch.setattr
?模拟包似乎能够使用副作用来做到这一点。我如何使用 pytest 做到这一点?
monkeypatch
是 pytest 中的一个很棒的工具,允许您替换当前测试范围内的任何函数。最棒的事情之一是甚至可以修补构造函数。然而不幸的是,我在修补析构函数时遇到了麻烦。它似乎只有在测试成功时才有效。如果测试失败,则调用常规构造函数。考虑这个代码:
class MyClass:
def __init__(self):
print("Constructing MyClass")
def __del__(self):
print("Destroying MyClass")
def test_NoPatch():
c = MyClass()
def test_Patch(monkeypatch, mocker):
monkeypatch.setattr(MyClass, '__init__', mocker.MagicMock(return_value=None))
monkeypatch.setattr(MyClass, '__del__', mocker.MagicMock(return_value=None))
c = MyClass()
def test_PatchWithFailure(monkeypatch, mocker):
monkeypatch.setattr(MyClass, '__init__', mocker.MagicMock(return_value=None))
monkeypatch.setattr(MyClass, '__del__', mocker.MagicMock(return_value=None))
c = MyClass()
assert False
Run Code Online (Sandbox Code Playgroud)
将给出以下结果:
====================================================================================================== test session starts ======================================================================================================
platform linux -- Python 3.8.5, pytest-6.2.2, py-1.10.0, pluggy-0.13.1 -- /home/julian/devel/tests/test_pytest_monkeypatch/testenv/bin/python3
cachedir: .pytest_cache
rootdir: /home/julian/devel/tests/test_pytest_monkeypatch
plugins: mock-3.5.1
collected 3 items
test.py::test_NoPatch Constructing MyClass
Destroying MyClass
PASSED
test.py::test_Patch PASSED
test.py::test_PatchWithFailure FAILED …
Run Code Online (Sandbox Code Playgroud) 我正在使用"如何在Perl中修补实例方法?"的开头给出的技术修补程序包..我遇到的问题是原始子例程使用了一个包级my
变量,修补后的子例程似乎无法通过完整路径规范或隐式使用来访问.
有没有办法以这种方式获取用于修补子例程的数据范围?
我有一些自定义逻辑需要在每次反转URL时执行,即使对于第三方应用程序也是如此.我的项目是一个多租户Web应用程序,并根据URL识别租户.没有一个有效的URL不包含租户标识符.
我已经有了一个包装函数reverse
,但现在我需要一种方法来告诉每个已安装的应用程序使用它.包装器reverse
使用线程本地将标识符注入到生成的URL中.我可以把这个函数写成装饰器reverse
,但我不知道在哪里做实际的装饰.
适度坚定的约束:我已经使用了3个第三方应用程序,我可能会添加更多.解决方案不应要求我修改所有这些第三方应用程序的源代码.如果有更简单的方法,我不喜欢在多个第三方源树之上维护补丁的想法.我可以清楚地说明reverse
装饰过的文件.
原始问题:我可以在哪里进行这样的更改以保证它适用于每次调用reverse
?
可能的替代问题:确保每个URL(包括第三方应用程序生成的URL)获取租户标识符的更好方法是什么?顺便说一句,除了在URL中嵌入tenant-id之外,我还有更好的办法处理这些问题.这个决定现在已经很好了.谢谢.
谢谢.
我的应用程序试图用一些基本的审计/日志记录功能包装django.contrib.auth.views登录和注销视图.我遵循django-axes项目中描述的处方,并且在运行服务器和其他一些测试时,它按预期工作,透明地没有问题.
代码如下:
from django.contrib.auth import views as auth_views
from myapp.watchers import watch_login
class WatcherMiddleware(object):
def __init__(self):
auth_views.login = watch_login(auth_views.login)
Run Code Online (Sandbox Code Playgroud)
和
def watch_login(func):
def decorated_login(request, *args, **kwargs):
#do some stuff
response = func(request, *args, **kwargs)
#more stuff
return response
return decorated_login
Run Code Online (Sandbox Code Playgroud)
网址:
#Edit: Added project's urls - just using vanilla django's auth login
(r'^accounts/login/$', 'django.contrib.auth.views.login',{"template_name":settings.LOGIN_TEMPLATE }),
Run Code Online (Sandbox Code Playgroud)
但是,在我们的构建工作流程中,我们遇到了django.contrib.auth.tests.views中的一些问题.
具体来说,这些是django.contrib.auth中失败的测试:
ERROR: test_current_site_in_context_after_login (django.contrib.auth.tests.views.LoginTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Python26\lib\site-packages\django\contrib\auth\tests\views.py", line 192, in test_current_site_in_context_after_login
response = self.client.get(reverse('django.contrib.auth.views.login'))
File "C:\Python26\lib\site-packages\django\core\urlresolvers.py", line …
Run Code Online (Sandbox Code Playgroud) 我正在做很多步骤.其中之一是使用gevent + monkey补丁
from gevent import monkey; monkey.patch_all()
Run Code Online (Sandbox Code Playgroud)
一切都很好.但是我可以在使用它之后将其取消吗?我想返回我的默认套接字函数.
在Python中,术语monkey patch
仅指运行时对类或模块的动态修改.作为初学者,我很难理解python上下文中的这个术语.任何人都可以通过现实世界的例子向我解释我们究竟是怎么做的?
我坚持一个真实世界的例子(尽可能简单)来理解我们必须在哪些场景中完成这样的任务?
我想改变现有项目中的I18n.translate方法.
require 'I18n'
module I18n
alias_method :old_translate, :translate
def translate(*args)
old_translate(*args) + 'blabla'
end
alias_method :t, :translate
end
Run Code Online (Sandbox Code Playgroud)
这会产生:
未捕获的异常:缺少帮助文件助手/ I18n.rb
我做错了什么以及我应该把这段代码放在哪里?
要编写splat运算符的自定义结果,必须实现to_a
方法.String类的示例:
class String
def to_a
self.split //
end
end
irb> res = *'text'
=> ["t", "e", "x", "t"]
Run Code Online (Sandbox Code Playgroud)
但是如果没有上面的monkeypatch,String类对to_a
方法一无所知:
irb> String.respond_to? :to_a
=> false
Run Code Online (Sandbox Code Playgroud)
所以问题是,在标准的"未修补"的String对象上应用splat运算符时会调用什么方法?
irb> res = *'text'
=> ['text']
Run Code Online (Sandbox Code Playgroud) 我正在尝试"猴子补丁" 列表的一个实例.请注意,这不是我的清单.我无法控制它的创作.据我所知,这在2.7中是不可能的.我对吗?是否有可能在3.x?
monkeypatching ×10
python ×6
django ×2
pytest ×2
decorator ×1
gevent ×1
list ×1
mocking ×1
packages ×1
perl ×1
python-3.x ×1
rails-i18n ×1
reverse ×1
ruby ×1
scope ×1
unit-testing ×1