【问题标题】:python unittest: can't call decorated testpython unittest:不能调用装饰测试
【发布时间】:2011-09-12 19:41:00
【问题描述】:

我有一个相当大的测试套件,我装饰了一些 test_* 函数。现在我不能用./test.py MySqlTestCase.test_foo_double 给他们打电话,python3.2 抱怨说:ValueError: no such test method in <class '__main__.MySqlTestCase'>: result。我的装饰器代码如下所示:

def procedure_test(procedure_name, arguments_count, returns):

    '''Decorator for procedure tests, that simplifies testing whether procedure
    with given name is available, whether it has given number of arguments
    and returns given value.'''

    def decorator(test):
        def result(self):
            procedure = self.db.procedures[self.case(procedure_name)]
            self.assertEqual(len(procedure.arguments), arguments_count)
            self.assertEqual(procedure.returns, 
                             None if returns is None else self.case(returns))
            test(self, procedure)
        return result
    return decorator

及测试方法:

@procedure_test('foo_double', 0, 'integer')
def test_foo_double(self, procedure):
    self.assertEqual(procedure.database, self.db)
    self.assertEqual(procedure.sql, 'RETURN 2 * value')
    self.assertArguments(procedure, [('value', 'int4')])

【问题讨论】:

    标签: python unit-testing decorator


    【解决方案1】:

    这是解决此问题的一种简单方法。

    from functools import wraps
    
    def your_decorator(func):
        @wraps(func)
        def wrapper(self):
            #Do Whatever
            return func(self)
        return wrapper
    
    class YourTest(APITestCase):
        @your_decorator
        def example(self):
            #Do your thing
    

    【讨论】:

      【解决方案2】:

      基于this 帖子:

      你可以这样做:

      def decorator(test):
          def wrapper(self):
              # do something interesting
              test(self)
              # do something interesting
          wrapper.__name__ = test.__name__
          return wrapper
      

      @functools.wrap 的方法相比,此解决方案有两个优点:

      • 不需要导入任何东西
      • 创建装饰器时不需要知道测试名称

      由于该解决方案的第二个特性,可以为许多测试创建装饰器。

      【讨论】:

      • 这是一击必杀的爆头。必须是我接受的。
      • 请注意,functools.wraps 不仅仅是设置名称,例如保存文档字符串。而在装饰器中wraps 的正常使用是 ``` def decorator(func): @wraps(func) wrapper(*args) ... ```` 它可以类似地包装任意命名的测试用例。跨度>
      【解决方案3】:

      这对我有帮助:

      from functools import wraps
      

      ...

      @wraps(procedure_name)
      def decorator(test):
      

      【讨论】:

        【解决方案4】:

        我认为问题在于装饰函数没有相同的名称,而且它不满足被视为测试方法的模式。

        使用functools.wrap 装饰decorator 应该可以解决您的问题。更多信息here

        【讨论】:

          猜你喜欢
          • 2011-02-13
          • 1970-01-01
          • 2017-09-20
          • 1970-01-01
          • 2012-11-01
          • 2017-08-20
          • 1970-01-01
          • 2021-04-06
          • 1970-01-01
          相关资源
          最近更新 更多