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