unittest.TestCase and functools.partial don't seem to mix

Peter Otten __peter__ at web.de
Tue Oct 6 06:43:47 EDT 2009


Joel Smith wrote:

> Hi List,
> I want to make some test case classes that can have some data passed in
> to modify the way they behave. I can't see a straightforward manner to
> pass data to an __init__() method of a class derived from
> unittest.TestCase, or to pass data to a test function within that
> class.  Being a C++ guy, I thought "If only Python had something
> equivalent to boost::bind, I'd be fine," and then I discovered
> functools.partial. I found a post showing how to create classes using
> partial, and I thought I was good to go. The post I found is here:
> 
> http://mail.python.org/pipermail/bangpypers/2008-December/000974.html
> 
> So I adapted that code to see if it worked in the context of unittest.
> When I run the code, it acts like the parameter I provided with partial
> isn't even there. Any ideas?
> 
> #!/usr/bin/python
> 
> import functools
> import unittest
> 
> class GenericWindow:
>    def __init__(self, name, width, height, color='white'):
>       print('Name: %s, width: %d, height: %d, color: %s' % (name, width,
> height, color))
> 
> class TestGenericWindow(unittest.TestCase):
>    def __init__(self, methodName, color):
>       unittest.TestCase.__init__(self, methodName)
>       print('color: %s' % color)
>       self.color = color
> 
>    def testit():
>       GenericWindow('foo', width=100, height=100, color=self.color)
> 
> def suite():
>    s = unittest.Suite()
>    BrownWindowTest = functools.partial(TestGenericWindow, color='brown')
>    BlueWindowTest = functools.partial(TestGenericWindow, color='blue')
>    GreenWindowTest = functools.partial(TestGenericWindow, color='green')
>    s.addTest(unittest.makeSuite(BrownWindowTest))
>    s.addTest(unittest.makeSuite(BlueWindowTest))
>    s.addTest(unittest.makeSuite(GreenWindowTest))
>    return s
> 
> if __name__ == '__main__': #unittest.main()
>    unittest.main()
> 
> That code gives the following:
> 
> Traceback (most recent call last):
>    File "./functools.partial.py", line 32, in <module>
>      unittest.main()
>    File "/usr/lib/python2.6/unittest.py", line 816, in __init__
>      self.parseArgs(argv)
>    File "/usr/lib/python2.6/unittest.py", line 837, in parseArgs
>      self.test = self.testLoader.loadTestsFromModule(self.module)
>    File "/usr/lib/python2.6/unittest.py", line 559, in loadTestsFromModule
>      tests.append(self.loadTestsFromTestCase(obj))
>    File "/usr/lib/python2.6/unittest.py", line 550, in
>    loadTestsFromTestCase
>      return self.suiteClass(map(testCaseClass, testCaseNames))
>  TypeError: __init__() takes exactly 3 arguments (2 given)
> 
> Thanks for having a look,
> Joel

By default unittest.main() looks for subclasses of unittest.TestCase and 
generates test cases for every method that starts with "test". From that 
point of view suite() is just an ordinary function and will not even be 
called. There are a lot more problems with your code that suggest that you 
should carefully read the unittest documentation, and maybe even have a look 
at its source code.

Here's what became of your code when I tried to make it run:

import unittest

class GenericWindow:
    def __init__(self, name, width, height, color='white'):
        print('Name: %s, width: %d, height: %d, color: %s' % (name, width, 
height, color))

class TestGenericWindow(unittest.TestCase):
    def __init__(self, methodName, color):
        unittest.TestCase.__init__(self, methodName)
        print('color: %s' % color)
        self.color = color

    def testit(self):
        GenericWindow('foo', width=100, height=100, color=self.color)

def suite():
    return unittest.TestSuite([
            TestGenericWindow("testit", color="brown"),
            TestGenericWindow("testit", color='blue'),
            TestGenericWindow("testit", color='green'),
    ])

if __name__ == '__main__':
    import sys
    argv = sys.argv[:]
    argv.insert(1, "suite")
    unittest.main(argv=argv)








More information about the Python-list mailing list