0

I am simply not experienced enough in Python OO programming to know how this is done: If I have several classes that are subclasses of a unittest.TestCase subclass. How should the superclass' methods reference variables of the subclasses when the latter call these methods? Let me try to illustrate it with this, probably wrong, example:

import unittest

class TestSuper(unittest.TestCase):

    def test_method(self):
        # do something, e.g.
        pass

class TestSub1(TestSuper):

    def setUp(self):
        self.some_parameter = 1

class TestSub2(TestSuper):

    def setUp(self):
        self.some_parameter = 2

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

Now, I cannot figure out how to correcty reference TestSub1.parameter or TestSub2.parameter, respectively, when TestSuper.test_method is called from the subclasses.

I am inspired by https://stackoverflow.com/a/25695512/865169, but here I am trying achieve having multiple test cases that do the same but only differ in their set-up. I can of course achieve all this by just copy-pasting my test case definitions, but I find that bad coding practice.

Community
  • 1
  • 1
Thomas Arildsen
  • 1,079
  • 2
  • 14
  • 31

1 Answers1

3

Just use self.some_parameter; self is always bound to the right instance here.

However, take into account that unittest.main() will run test_method on *all three test cases (the baseclass included), so you'll have to provide a default value for some_parameter on the base class.

If you don't want TestSuper to be seen as a test case, don't inherit from unittest.TestCase. Use it as a mix-in instead:

import unittest

class TestMixin(object):
    def test_method(self):
        # do something, e.g.
        pass

class TestSub1(unittest.TestCase, TestMixin):
    def setUp(self):
        self.some_parameter = 1

class TestSub2(unittest.TestCase, TestMixin):
    def setUp(self):
        self.some_parameter = 2

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

Now unittest.main() will only find two test cases (TestSub1 and TestSub2) and run test_method only on those cases.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Well, I was a bit scared of the mixin approach due to http://nedbatchelder.com/blog/201210/multiple_inheritance_is_hard.html – Thomas Arildsen Jan 22 '16 at 10:07
  • @vadim-p suggests hiding the baseclass inside a non-TestCase class in order to skip the test in the baseclass: http://stackoverflow.com/a/25695512/865169 – Thomas Arildsen Jan 22 '16 at 10:08
  • @ThomasArildsen: you are not providing the same methods in a base and a mixin. Proper use of mixins is not that hard though. Also see https://www.youtube.com/watch?v=EiOglTERPEo for a great explanation of what goes on with multiple inheritance. – Martijn Pieters Jan 22 '16 at 10:14
  • @ThomasArildsen: the hiding 'hack' is that, a hack, and is not needed. It causes confusion and reduces readability. – Martijn Pieters Jan 22 '16 at 10:15
  • Hmm, I don't understand this. In my somewhat more complicated real test, the hiding hack works, but the mixin does not. In the latter case, the error messages seem to indicate that Python expects self to refer to TestMixin, so it cannot find the parameter that is in TestSub1, for example. – Thomas Arildsen Jan 22 '16 at 10:28
  • @ThomasArildsen: then your mixin is (indirectly?) still inheriting from `TestCase`; it is being run. – Martijn Pieters Jan 22 '16 at 10:33
  • Oh, right. The mixin needs to inherit `assert`-functions from `unittest` which are usually run as `self.assert`... in tests. How to do that then? – Thomas Arildsen Jan 22 '16 at 10:38
  • @ThomasArildsen: it doesn't have to inherit those. The `assert*` methods will be available via the subclasses. – Martijn Pieters Jan 22 '16 at 10:39
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/101391/discussion-between-thomas-arildsen-and-martijn-pieters). – Thomas Arildsen Jan 22 '16 at 10:41