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

J

Joel Smith

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
 
P

Peter Otten

Joel said:
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)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top