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' object has no attribute '__name__'
这是@wraps(func)
,我的问题是为什么func
这里是TestPaymentMethodEndpoints
的一个实例,而不是绑定的方法?
此外,如果我移除@wraps
装饰器,则测试运行并通过。
我预计不会发现测试,因为func_wrapper
不会以test_*
开头,即使它被发现也会失败。
有关正在发生的事情以及我将如何进行此操作的任何见解?
修改
因此,即使装饰工厂的参数具有默认值,您仍然需要在调用它时放置()
。
但是,我仍然希望听到有关测试通过/首先被发现时发生的事情的解释。
class TestPaymentMethodEndpoints(APITestCase):
@register_processor()
def test_put_detail_cannot_change_processor(self):
self.assertEqual(True, False)
现在我觉得有意义:D,你每天都学到新的东西!
答案 0 :(得分:1)
我想你现在问“unittest
模块怎么能找到包含在名称不能启动test
的函数中的测试用例?”
答案是因为unittest
不使用函数的名称来查找要运行的方法,它使用属性名称测试用例类来查找它们。
因此,请尝试运行以下代码:
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)