在Python中将不同的值传递给单元测试的装饰器
在我的一个类方法中,我试图修改传递给装饰器的参数。代码如下所示:在Python中将不同的值传递给单元测试的装饰器,python,unit-testing,decorator,python-decorators,Python,Unit Testing,Decorator,Python Decorators,在我的一个类方法中,我试图修改传递给装饰器的参数。代码如下所示: class MyClass(object): @tryagain(retries=3) def mymethod(self, arg): ... do stuff ... @tryagain(retries=self.retries) def mymethod(self, arg): ... do stuff ... 我的问题是,在运行单元测试时,我想将“retries”变量更改为小于3的值,但
class MyClass(object):
@tryagain(retries=3)
def mymethod(self, arg):
... do stuff ...
@tryagain(retries=self.retries)
def mymethod(self, arg):
... do stuff ...
我的问题是,在运行单元测试时,我想将“retries”变量更改为小于3的值,但对于生产代码,将其保持为“3”。不幸的是,看起来我做不到这样的事情:
class MyClass(object):
@tryagain(retries=3)
def mymethod(self, arg):
... do stuff ...
@tryagain(retries=self.retries)
def mymethod(self, arg):
... do stuff ...
或
因为类在参数传递给装饰器的时候没有定义(据我所知)
我还尝试在模块中添加变量,如下所示:
retries = 1
def MyClass(object):
@tryagain(retries=retries)
def mymethod(self, arg):
... do stuff ...
但是,我似乎无法在单元测试中修改“重试”的值。有没有其他方法可以完成我想做的事情?我假设您尝试减少重试次数以提高测试速度 如果是这样,修改重试次数变量似乎不是最好的方法。相反,您可以先在不使用decorator的情况下对函数
mymethod
进行单元测试,然后创建mymethod
的模拟函数。让我们称它为mock_mymethod
,用@tryagain
装饰它,并测试“tryagain”的逻辑是否真的有效
检查模块以了解如何创建模拟实例,这篇关于
mock
的文章也值得一读。您可以使用从调用代码设置的环境变量(在这里输入默认值可能会更好)
import os
# ...
class MyClass(object):
@tryagain(retries=int(os.environ['project_num_retries']))
def mymethod(self, arg):
print("mymethod")
或者使用“全局”类型的模块,例如:project\u settings.py
包含:
num_retries = 3
然后
但我不确定用测试信息装饰代码是您真正应该做的事情——那么:
class MyClass(object):
def mymethod(self, arg):
print("mymethod")
然后在类似于unittests.py的内容中:
DEV_TESTS = True # Change to False for production
num_retries = 3 if not DEV_TESTS else 1
import <your class>
class UnitTests():
def __init__(self):
self.c = <your_class>.MyClass()
@tryagain(retries=num_retries)
def test_mymethod(self):
self.c.mymethod("Foo")
t = UnitTests()
t.test_mymethod()
注意,我使用了下面的@tryagain
装饰器的简单示例,您的示例可能更复杂,需要对示例进行一些调整:
def tryagain(retries):
def wrap(f):
def wrapped_f(*args,**kwargs):
for _ in xrange(retries):
f(*args,**kwargs)
return wrapped_f
return wrap
是的,这是正确的。我想我的下一个问题是,没有decorator我如何测试mymethod?看起来我可以修补decorator,但它不是那么简单。我必须仔细阅读。尝试mocktryagain
并将其返回值设置为相同的输入函数,然后测试mymethod
。这实际上是w没有任何装饰效果。在那之后,mockmymethod
和testtryagain
。我会尝试一下。如果你认真对待unittest,mock绝对值得学习,我认为它非常适合你在这种特殊情况下的需要。是的,我第一次在这个项目上使用mock,所以我有点熟悉,b但我仍在学习一些东西。昨晚我终于能够在一些工作之后找到正确修补装饰器的地方,我认为这是一个方向。我认为设置环境变量将满足我的需要。可能还不清楚,但我正在尝试绕过(或缩短)我运行单元测试所需的时间。我希望@tryagain修饰生产代码,因为我希望在第一次失败时再次调用“mymethod”。我不希望在运行测试时启动它,因为在测试某些失败案例时,需要很长时间才能恢复(它有一个回退时间).Oh,所以@tryagain
不是测试修饰符,而是在测试时要修改参数的生产修饰符,明白了。忽略答案的第二部分。
def tryagain(retries):
def wrap(f):
def wrapped_f(*args,**kwargs):
for _ in xrange(retries):
f(*args,**kwargs)
return wrapped_f
return wrap