通过元类操作unittest的Fixture类方法

2024-04-26 04:38:42 发布

您现在位置:Python中文网/ 问答频道 /正文

我想为^{}的子类创建一个元类,它将导致所有方法在开始和结束时都进行日志记录,例如the ^{}s ^{} and ^{} and their variants。你知道吗

不幸的是,unittest框架对方法的名称非常特别,修改它们会导致框架找不到它们。使用this question的答案,我得到如下结果:

  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方法。如果我尝试做与上述完全相同的事情,即添加

          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)

但是,如果我尝试properly add a dynamic classmethod

          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根本不调用这个fixture方法。你知道吗

注意this question问了一些类似的问题,但是公认的答案假设这些方法不是类方法,因此这是完全错误的。)


Tags: 方法lambdanametestselfnewiffunction