0

I have the following construct, in which I derive a class from unittest.TestCase, in which a method is called that is defined in the actual test class MyTests.

import unittest

class TestCase1(unittest.TestCase):

    @classmethod
    def setUpClass(cls):  
        print cls.extra()

class TestCase2(TestCase1):

    @classmethod
    def setUpClass(cls):
        TestCase1.setUpClass()

class MyTests(TestCase1):

    @classmethod
    def extra(cls):
        return 42

    def test1(self):
        pass

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

The above code, as it stands, works as expected. When I execute the tests, the setUpClass of TestCase1 is run, which executed extra() defined in MyTests.

The problem comes into play when I want to use TestCase2 instead TestCase1, i.e. when I change the '1' to '2' in the following line:

class MyTests(TestCase2): # using TestCase2 instead

The idea is that setUpClass of TestCase2 is called, which in itself calls setUpClass from the basic class, i.e. TestCase1, which executes the method extra. However, I get an attribute error:

AttributeError: type object 'TestCase1' has no attribute 'extra'

I seem to misunderstand some concepts here. I would have expected my code to work in both cases (maybe there is some error), or to fail in both cases. Any ideas what here might be wrong or how I can fix the problem are greatly appreciated.

Alex
  • 41,580
  • 88
  • 260
  • 469

2 Answers2

2

The reason why is that when it is inheriting from TestCase2 the cls passed to when TestCase1.setUpClass() is called is of the type TestCase1, which has no extra() method. When called from MyTests, it cls is an instance of MyTests which has an extra method.

super passes the cls parameter from MyTests.setUpClass(cls) to TestCase1.setUpClass(cls). So when it reaches TestCase1, cls has an extra() method.

Stephen
  • 2,365
  • 17
  • 21
1

I highly recommend using super instead of TestCase1.setUpClass().

Community
  • 1
  • 1
aisbaa
  • 9,867
  • 6
  • 33
  • 48