How to test Python function decorators?
Solution 1
Take a look at the tests in the standard library for examples: http://hg.python.org/cpython/file/3.2/Lib/test/test_functools.py#l553
I usually add some instrumentation to the function being wrapped so that I can monitor the calls.
Instead of memoizing the test function at the module level, I create the memoized function inside the test so that a new one is created for each test and for each decorator variant.
Solution 2
What about the rather complicated
def mkfib(strategy):
@Memoizer(strategy=strategy)
def fib(x):
if x < 2:
return 1
else:
return fib(x-1) + fib(x-2)
return fib
This way you could do
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)
Related videos on Youtube
Comments
-
Ceasar Bautista over 1 year
I'm trying to write unit tests to ensure correctness of various decorators I've written. Here's the start of the code I'm trying to write:
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()
While this works decently for the MRU strategy I have above, I plan to write additional strategies, in which case I'll need to decorate with the fib function in different ways. (Recall that because fib calls fib, setting fib2 = memoize(fib) does not memoize intermediate values so that will not work.) What is the correct way to test the other decorators?
-
Ceasar Bautista about 12 yearsAh, right. Not sure why it didn't cross my mind not to use anything then fibonacci numbers.
-
Raymond Hettinger about 12 yearsI would be interested in seeing your MRU code when you're done. Hopefully, you will post a link.
-
Ceasar Bautista about 12 yearsSure! The code for my memoizer is here: github.com/Ceasar/memoizer EDIT: I think my mru.py should actually be called lru.py