I currently have a few unit tests which share a common set of tests. Here\'s an example:
import unittest
class BaseTest(unittest.TestCase):
def testCo
You can solve this problem with a single command:
del(BaseTest)
So the code would look like this:
import unittest
class BaseTest(unittest.TestCase):
def testCommon(self):
print 'Calling BaseTest:testCommon'
value = 5
self.assertEquals(value, 5)
class SubTest1(BaseTest):
def testSub1(self):
print 'Calling SubTest1:testSub1'
sub = 3
self.assertEquals(sub, 3)
class SubTest2(BaseTest):
def testSub2(self):
print 'Calling SubTest2:testSub2'
sub = 4
self.assertEquals(sub, 4)
del(BaseTest)
if __name__ == '__main__':
unittest.main()
I made about the same than @Vladim P. (https://stackoverflow.com/a/25695512/2451329) but slightly modified:
import unittest2
from some_module import func1, func2
def make_base_class(func):
class Base(unittest2.TestCase):
def test_common1(self):
print("in test_common1")
self.assertTrue(func())
def test_common2(self):
print("in test_common1")
self.assertFalse(func(42))
return Base
class A(make_base_class(func1)):
pass
class B(make_base_class(func2)):
def test_func2_with_no_arg_return_bar(self):
self.assertEqual("bar", func2())
and there we go.
Change the BaseTest method name to setUp:
class BaseTest(unittest.TestCase):
def setUp(self):
print 'Calling BaseTest:testCommon'
value = 5
self.assertEquals(value, 5)
class SubTest1(BaseTest):
def testSub1(self):
print 'Calling SubTest1:testSub1'
sub = 3
self.assertEquals(sub, 3)
class SubTest2(BaseTest):
def testSub2(self):
print 'Calling SubTest2:testSub2'
sub = 4
self.assertEquals(sub, 4)
Output:
Ran 2 tests in 0.000s
Calling BaseTest:testCommon Calling
SubTest1:testSub1 Calling
BaseTest:testCommon Calling
SubTest2:testSub2
From the documentation:
TestCase.setUp()
Method called to prepare the test fixture. This is called immediately before calling the test method; any exception raised by this method will be considered an error rather than a test failure. The default implementation does nothing.
Here is a solution that uses only documented unittest features an that avoids having a "skip" status in your test results:
class BaseTest(unittest.TestCase):
def __init__(self, methodName='runTest'):
if self.__class__ is BaseTest:
# don't run these tests in the abstract base implementation
methodName = 'runNoTestsInBaseClass'
super().__init__(methodName)
def runNoTestsInBaseClass(self):
pass
def testCommon(self):
# everything else as in the original question
How it works: per the unittest.TestCase documentation, "Each instance of TestCase will run a single base method: the method named methodName." The default "runTests" runs all the test* methods on the class—that's how TestCase instances normally work. But when running in the abstract base class itself, you can simply override that behavior with a method that does nothing.
A side effect is your test count will increase by one: the runNoTestsInBaseClass "test" gets counted as a successful test when it's run on BaseClass.
(This also works in Python 2.7, if you're still on that. Just change super()
to super(BaseTest, self)
.)
Use multiple inheritance, so your class with common tests doesn't itself inherit from TestCase.
import unittest
class CommonTests(object):
def testCommon(self):
print 'Calling BaseTest:testCommon'
value = 5
self.assertEquals(value, 5)
class SubTest1(unittest.TestCase, CommonTests):
def testSub1(self):
print 'Calling SubTest1:testSub1'
sub = 3
self.assertEquals(sub, 3)
class SubTest2(unittest.TestCase, CommonTests):
def testSub2(self):
print 'Calling SubTest2:testSub2'
sub = 4
self.assertEquals(sub, 4)
if __name__ == '__main__':
unittest.main()
Just rename the testCommon method to something else. Unittest (usually) skips anything that doesn't have 'test' in it.
Quick and simple
import unittest
class BaseTest(unittest.TestCase):
def methodCommon(self):
print 'Calling BaseTest:testCommon'
value = 5
self.assertEquals(value, 5)
class SubTest1(BaseTest):
def testSub1(self):
print 'Calling SubTest1:testSub1'
sub = 3
self.assertEquals(sub, 3)
class SubTest2(BaseTest):
def testSub2(self):
print 'Calling SubTest2:testSub2'
sub = 4
self.assertEquals(sub, 4)
if __name__ == '__main__':
unittest.main()`