How to test Python function decorators?

13,686

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)
Share:
13,686

Related videos on Youtube

Ceasar Bautista
Author by

Ceasar Bautista

Python and web development

Updated on June 04, 2022

Comments

  • Ceasar Bautista
    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
    Ceasar Bautista about 12 years
    Ah, right. Not sure why it didn't cross my mind not to use anything then fibonacci numbers.
  • Raymond Hettinger
    Raymond Hettinger about 12 years
    I would be interested in seeing your MRU code when you're done. Hopefully, you will post a link.
  • Ceasar Bautista
    Ceasar Bautista about 12 years
    Sure! The code for my memoizer is here: github.com/Ceasar/memoizer EDIT: I think my mru.py should actually be called lru.py