Я хотел бы иметь метакласс для подклассов unittest.TestCase
, что приведет к регистрации в журнале всех методов при их запуске и завершении, включая, например, @classmethod
s setUp
и tearDown
и их варианты.
К сожалению, фреймворк unittest
очень требователен к именам методов, и их изменение приводит к тому, что фреймворк не находит их. Используя ответ на этот вопрос , у меня есть что-то вроде следующего:
class _UTMeta(type):
def __new__(cls, name, bases, dict_):
new_dict = {}
for fn_name, fn in dict_.items():
if fn_name.startswith('test_'):
new_dict[fn_name] = lambda self: _UTMeta._wrapped_test_function(self, fn_name, fn)
new_dict[fn_name].__name__ = fn_name # (**)
else:
new_dict[fn_name] = fn
return type.__new__(cls, name, bases, new_dict)
@staticmethod
def _wrapped_test_function(self, name, fn):
print 'starting', name
_test_logger.info('starting ' + name)
print 'finished', name
Обратите внимание на строку с комментарием # (**)
— без него unittest
не распознает методы как тестовые.
Это работает для обычных методов test_*
, но не для classmethod
s. Чтобы проиллюстрировать проблему, я буду использовать classmethod setUpClass
. Если я попытаюсь сделать то же самое, что и выше, то есть добавить
if fn_name == 'setUpClass':
new_dict[fn_name] = lambda self: _UTMeta._wrapped_test_function(self, fn_name, fn)
new_dict[fn_name].__name__ = fn_name
то я получаю:
ERROR: setUpClass (__main__._VersionDataTest)
TypeError: unbound method setUpClass() must be called with _VersionDataTest instance as first argument (got nothing instead)
Однако если я попытаюсь правильно добавить
if fn_name == 'setUpClass':
new_dict[fn_name] = classmethod(lambda self: _UTMeta._wrapped_test_function(self, fn_name, fn))
new_dict[fn_name].__name__ = fn_name
я получил
AttributeError: 'classmethod' object has no attribute '__name__'
Наконец, если я пропущу манипуляцию .__name__
, unittest
вообще не вызовет этот метод фиксации.
(Примечание этот вопрос задает что-то подобное, но принятый ответ предполагает, что эти методы не являются методами класса, и поэтому ИМХО совершенно неверен.)