luismartingil
luismartingil

Reputation: 1109

Python multiple inheritance unittest -

I'm trying to understand what happens when doing multiple inheritance using a unittest.TestCase class.

MyTest_DoesWork outputs what I expect, this is both setUp() and tearDown() being triggered. This is not happening with MyTest_DoesNotWork. Why is this happening? Any clue?

import unittest

class MyClassTest1(object):
    def setUp(self):
        print 'Setting up', self.__class__
    def test_a1(self):
        print "Running test_a1 for class", self.__class__
    def test_a2(self):
        print "Running test_a2 for class", self.__class__
    def tearDown(self):
        print 'Tearing down', self.__class__

class MyClassTest2(object):
    def setUp(self):
        print 'Setting up', self.__class__
    def test_b1(self):
        print "Running test_b1 for class", self.__class__
    def test_b2(self):
        print "Running test_b2 for class", self.__class__
    def tearDown(self):
        print 'Tearing down', self.__class__

class MyTest_DoesNotWork(unittest.TestCase, MyClassTest1, MyClassTest2):
    """
    Output:
    Running test_a1 for class <class '__main__.MyTest_DoesNotWork'>
    .Running test_a2 for class <class '__main__.MyTest_DoesNotWork'>
    .Running test_b1 for class <class '__main__.MyTest_DoesNotWork'>
    .Running test_b2 for class <class '__main__.MyTest_DoesNotWork'>
    """
    pass

class MyTest_DoesWork(MyClassTest1, MyClassTest2, unittest.TestCase):
    """
    Output:
    Setting up <class '__main__.MyTest_DoesWork'>
    Running test_a1 for class <class '__main__.MyTest_DoesWork'>
    Tearing down <class '__main__.MyTest_DoesWork'>
    .Setting up <class '__main__.MyTest_DoesWork'>
    Running test_a2 for class <class '__main__.MyTest_DoesWork'>
    Tearing down <class '__main__.MyTest_DoesWork'>
    .Setting up <class '__main__.MyTest_DoesWork'>
    Running test_b1 for class <class '__main__.MyTest_DoesWork'>
    Tearing down <class '__main__.MyTest_DoesWork'>
    .Setting up <class '__main__.MyTest_DoesWork'>
    Running test_b2 for class <class '__main__.MyTest_DoesWork'>
    Tearing down <class '__main__.MyTest_DoesWork'>
    """
    pass

if __name__ == "__main__":
    unittest.main()

Upvotes: 10

Views: 3763

Answers (1)

reteptilian
reteptilian

Reputation: 923

Python's method resolution order causes this. With your inheritance structure, it is resolving in the order you declared the parent classes, left to right.

So with MyTest_DoesNotWork, python is going to hit the unittest.TestCase implementations of setUp and tearDown, which do not do anything. Because unittest.TestCase.setUp is not written to be cooperative and call other superclass setUp methods, it just stops there and nothing gets printed.

With MyTest_DoesWork, python will instead resolve to MyClassTest1 first. Just like unittest.TestCase, you haven't written your setUp and tearDown methods to cooperatively call superclass methods. So it stops there and never calls the MyClassTest2 methods. So I am guessing that even this actually isn't working as you expected. Change your MyClassTest1 setUp and tearDown methods to print out "MyClassTest1" instead of self.class and you will see that it's the one being called all the time. MyClassTest2 setUp and tearDown are never called.

Upvotes: 7

Related Questions