def register_processor2(processor_name='SomeProcessor'):
def decorator(func):
class SomeProcessor(GenericPaymentProcessor, TriggeredProcessorMixin):
name = processor_name
transaction_class = Transaction
@staticmethod
def setup(data=None):
pass
@wraps(func)
def func_wrapper(*args, **kwargs):
PaymentProcessorManager.register(SomeProcessor)
result = func(*args, **kwargs)
PaymentProcessorManager.unregister(SomeProcessor)
return result
return func_wrapper
return decorator
def register_processor(func):
class SomeProcessor(GenericPaymentProcessor, TriggeredProcessorMixin):
name = 'SomeProcessor'
transaction_class = Transaction
@staticmethod
def setup(data=None):
pass
@wraps(func)
def func_wrapper(*args, **kwargs):
PaymentProcessorManager.register(SomeProcessor)
result = func(*args, **kwargs)
PaymentProcessorManager.unregister(SomeProcessor)
return result
return func_wrapper
class TestPaymentMethodEndpoints(APITestCase):
@register_processor
def test_put_detail_cannot_change_processor(self):
self.assertEqual(True, False)
好的,装饰器register_processor
按预期工作。测试失败了,但我想让内部类的名称可定制,所以我改用装饰器工厂实现。
问题是,当运行用 register_processor2
装饰的测试时,我得到以下结果:
AttributeError:“TestPaymentMethodEndpoints”对象没有属性“__name__”
这是来自@wraps(func)
,我的问题是为什么这里的func
是TestPaymentMethodEndpoints
的实例,而不是绑定(bind)方法?
此外,如果我删除 @wraps
装饰器,则测试将运行并通过。
我希望测试不会被发现,因为 func_wrapper
不是以 test_*
开头,即使被发现,它也应该失败。
对正在发生的事情以及我将如何去做有什么见解吗?
编辑
所以我发现即使装饰器工厂有具有默认值的参数,您在调用它时仍然需要放置 ()
。
但仍然希望听到关于测试通过/首先被发现时发生的情况的解释。
class TestPaymentMethodEndpoints(APITestCase):
@register_processor()
def test_put_detail_cannot_change_processor(self):
self.assertEqual(True, False)
现在想想,这是有道理的:D,天哪,你每天都学到新东西!
最佳答案
我认为您现在会问“unittest
模块如何找到已包装在名称不以 test
开头的函数中的测试用例?”
答案是因为 unittest
不使用函数的名称来查找要运行的方法,它使用属性名称 em> 测试用例类来查找它们。
因此尝试运行以下代码:
from unittest import TestCase
def apply_fixture(func):
def wrap_with_fixture(self):
print('setting up fixture...')
try:
func(self)
finally:
print('tearing down fixture')
return wrap_with_fixture
class MyTestCase(TestCase):
@apply_fixture
def test_something(self):
print('run test')
print('Attributes of MyTestCase: %s' % dir(MyTestCase))
print('test_something method: %s' % MyTestCase.test_something)
mtc = MyTestCase()
mtc.test_something()
您将看到 dir
的输出包含名称 test_something
:
Attributes of MyTestCase: ['__call__', ...lots of things..., 'test_something']
但该属性的值是包装函数wrap_with_fixture
:
test_something method: <function apply_fixture.<locals>.wrap_with_fixture at 0x10d90aea0>
当您考虑到创建函数时,您既创建了一个具有所提供名称的函数,又创建了一个具有相同名称的局部变量,并且装饰器 @
语法只是语法,这是有道理的糖,因此以下内容是创建测试用例类的同样有效但冗长的方法:
class MyTestCase(TestCase):
def test_something(self):
print('run test')
# Overwrite existing 'local' (or 'class' variable in this context)
# with a new value. We haven't deleted the test_something function
# which still exists but now is owned by the function we've created.
test_something = apply_fixture(test_something)
关于python - 采用单元测试方法的装饰器工厂,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40866611/