【问题标题】:How to test Python function decorators?如何测试 Python 函数装饰器?
【发布时间】:2011-12-20 11:42:04
【问题描述】:

我正在尝试编写单元测试以确保我编写的各种装饰器的正确性。这是我正在尝试编写的代码的开头:

import unittest

from memoizer import Memoizer
from strategies.mru import MRU


@Memoizer(strategy=MRU(maxsize=10))
def fib(x):
  if x < 2:
    return 1
  else:
    return fib(x-1) + fib(x-2)


class TestMemoizer(unittest.TestCase):

  def test_simple(self):
    self.assertEqual(fib(0), 1)
    self.assertEqual(fib(1), 1)
    self.assertEqual(fib(10), 89)


if __name__ == '__main__':
  unittest.main()

虽然这对我上面的 MRU 策略很有效,但我计划编写其他策略,在这种情况下,我需要以不同的方式使用 fib 函数进行装饰。 (回想一下,因为 fib 调用 fib,所以设置 fib2 = memoize(fib) 不会记住中间值,因此这不起作用。)测试其他装饰器的正确方法是什么?

【问题讨论】:

    标签: python unit-testing decorator


    【解决方案1】:

    以标准库中的测试为例:http://hg.python.org/cpython/file/3.2/Lib/test/test_functools.py#l553

    我通常会在被包装的函数中添加一些检测,以便我可以监控调用。

    我没有在模块级别记忆测试函数,而是在测试内部创建记忆函数,以便为每个测试和每个装饰器变体创建一个新函数。

    【讨论】:

    • 啊,对。不知道为什么我没有想到不使用斐波那契数字。
    • 我很想在您完成后查看您的 MRU 代码。希望你能发布一个链接。
    • 当然!我的 memoizer 的代码在这里:github.com/Ceasar/memoizer 编辑:我认为我的 mru.py 实际上应该被称为 lru.py
    【解决方案2】:

    比较复杂的呢

    def mkfib(strategy):
        @Memoizer(strategy=strategy)
        def fib(x):
          if x < 2:
            return 1
          else:
            return fib(x-1) + fib(x-2)
        return fib
    

    你可以这样做

    fib1 = mkfib(MRU(maxsize=10))
    self.assertEqual(fib1(0), 1)
    self.assertEqual(fib1(1), 1)
    
    fib2 = mkfib(MRU(maxsize=10)) # produces another cache
    self.assertEqual(fib2(0), 1)
    self.assertEqual(fib2(1), 1)
    

    【讨论】:

      猜你喜欢
      • 2011-02-13
      • 2014-09-20
      • 1970-01-01
      • 2020-05-19
      • 2017-08-20
      • 2017-08-27
      • 1970-01-01
      • 2018-03-07
      • 2021-01-20
      相关资源
      最近更新 更多