abstract test case using python unittest
I didn't quite understand what do you plan to do --the rule of thumb is "not to be smart with tests" - just have them there, plain written.
But to achieve what you want, if you inherit from unittest.TestCase, whenever you call unittest.main() your "abstract" class will be executed - I think this is the situation you want to avoid.
Just do this:Create your "abstract" class inheriting from "object", not from TestCase. And for the actual "concrete" implementations, just use multiple inheritance:inherit from both unittest.TestCase and from your abstract class.
import unittestclass Abstract(object): def test_a(self): print "Running for class", self.__class__class Test(Abstract, unittest.TestCase): passunittest.main()
update: reversed the inheritance order - Abstract
first so that its defintions are not overriden by TestCase
defaults, as well pointed in the comments bellow.
There's a very simple way that everyone has missed so far. And unlike several of the answers, it works with all test drivers, rather than failing the minute you switch between them.
Simply use inheritence as usual, then add:
del AbstractTestCase
at the end of the module.
Multiple inheritance isn't a great option here, chiefly for the two following reasons:
- None of the methods in
TestCase
usesuper()
so you'd have to list your class first for methods likesetUp()
andtearDown()
to work. - pylint will warn that the base class uses
self.assertEquals()
etc which aren't defined onself
at that point.
Here's the kludge I came up with: turn run()
into a no-op for the base class only.
class TestBase( unittest.TestCase ): def __init__( self, *args, **kwargs ): super( TestBase, self ).__init__( *args, **kwargs ) self.helper = None # Kludge alert: We want this class to carry test cases without being run # by the unit test framework, so the `run' method is overridden to do # nothing. But in order for sub-classes to be able to do something when # run is invoked, the constructor will rebind `run' from TestCase. if self.__class__ != TestBase: # Rebind `run' from the parent class. self.run = unittest.TestCase.run.__get__( self, self.__class__ ) else: self.run = lambda self, *args, **kwargs: None def newHelper( self ): raise NotImplementedError() def setUp( self ): print "shared for all subclasses" self.helper = self.newHelper() def testFoo( self ): print "shared for all subclasses" # test something with self.helperclass Test1( TestBase ): def newHelper( self ): return HelperObject1()class Test2( TestBase ): def newHelper( self ): return HelperObject2()