Reputation: 1926
I want to make a function that can be used in other unit tests in the script. Here is what I mean:
class TestSomething(unittest.TestCase):
def __init__(self, title, description):
self.title = title
self.description = description
self.tag = 'ts'
class TestSomething2(unittest.TestCase):
def __init__(self, title, description):
self.title = title
self.description = description
self.tag = 'ts2'
class TestWhatever(unittest.TestCase):
def test_whatever(self):
blah = TestSomething('Happy Gilmore', 'golf movie')
AttributeCheck(blah, 'Happy Gilmore', 'golf movie', 'ts')
class TestWhatever2(unittest.TestCase):
def test_whatever(self):
blah = TestSomething2('Toy Story', 'kids movie')
AttributeCheck(blah, 'Toy Story', 'kids movie', 'ts2')
class AttributeCheck(unittest.TestCase):
def __init__(self, element, title, description, tag):
super(AttributeCheck, self).__init__()
self.assertEqual(element.title, title)
self.assertEqual(element.description, description)
self.assertEqual(element.tag, tag)
def runTest(self): # this is what causes problems
print 'ok'
if __name__ == '__main__':
unittest.main()
The error I get is: TypeError: __init__() takes at least 3 arguments (2 given)
It basically tries to run the AttributeCheck and I think it runs runTest as if it were a test. However, I need the def runTest(self):
because if I don't have it then I get the: ValueError: no such test method in <class 'AttributeCheck'>: runTest
Upvotes: 1
Views: 590
Reputation: 710
You're using unittest.TestCase in a way that I haven't seen before, and I think is inconsistent with the documentation. My answer uses TestCase how I normally use it, hopefully it answers your question.
As far as having a function that can be used in multiple tests in the script, you can add a function to your test class that does a check for you. If it doesn't have "test" in the name, it won't be run as a test:
class TestWhatever(unittest.TestCase):
def test_whatever_does_something(self):
instance = Whatever('Happy Gilmore', 'golf movie', 'ts')
self._check_attributes(instance, 'Happy Gilmore', 'golf movie', 'ts')
def _check_attributes(self, element, title, description, tag):
self.assertEqual(element.title, title)
self.assertEqual(element.description, description)
self.assertEqual(element.tag, tag)
This isn't super useful, because your check method is limited to this class. You could import it into another test class if you wanted to, but that's a little messy as far as separation of responsibility goes.
I typically try to have 1 test class per test file, corresponding to exactly one production class. Each 'test' is a method inside a test class. Then, if there's a function I want to run from a lot of test classes, I put it in a separate file that I call "test_helpers.py". You shouldn't make your test helpers inherit from TestCase. You can define a failure exception and raise it from your test helper method.
The following code would be split up over 5 separate files in the same directory. The file names are in comments. Notice that the class Blah
lives in 'blah.py' and corresponds to a test class TestBlah
in test_blah.py. That's where you test everything to do with Blah.
I stole the code for the FailureException in test_helpers.py directly from the source code for unittest.
#blah.py
class Blah(object):
def __init__(self, title, description, tag):
self.title = title
self.description = description
self.tag = tag
#test_blah.py
from test_helpers import check_attributes
class TestBlah(unittest.TestCase):
def test_constructor(self):
blah = Blah('Happy Gilmore', 'golf movie', 'ts')
check_attributes(blah, 'Happy Gilmore', 'golf movie', 'ts')
#sub_blah.py
from blah import Blah
class SubBlah(Blah):
def __init__(self, title, description, tag):
super(SubBlah, self).__init__()
self.different_attribute = "I'm Different!"
#test_sub_blah.py
from test_helpers import check_attributes
class TestSubBlah(unittest.TestCase):
def test_constructor(self):
sub_blah = SubBlah('Toy Story', 'kids movie', 'sb')
check_attributes(blah, 'Toy Story', 'kids movie', 'sb')
self.assertEqual("I'm Different!", sub_blah.different_attribute)
#test_helpers.py
import Exception
def check_attributes(element, title, description, tag):
if not title == element.title:
raise FailureException(msg or '%r != %r' % (title, element.title))
if not description == element.description :
raise FailureException(msg or '%r != %r' % (description, element.description))
if not tag == element.tag:
raise FailureException(msg or '%r != %r' % (tag, element.tag))
class FailureException(Exception):
#pass here to make it a basic exception
pass
#If you need custom code, you can override __init__
#def __init__(self, message, errors):
#
# super(FailureException, self).__init__(message)
Upvotes: 2