简体   繁体   中英

python unittest inheritance - abstract test class

I need to use unittest in python to write some tests. I am testing the behavior of 2 classes, A and B , that have a lot of overlap in behavior because they are both subclasses of C , which is abstract. I would really like to be able to write 3 testing classes: ATestCase , BTestCase , and AbstractTestCase , where AbstractTestCase defines the common setup logic for ATestCase and BTestCase , but does not itself run any tests. ATestCase and BTestCase would be subclasses of AbstractTestCase and would define behavior/input data specific to A and B .

Is there a way to create an abstract class via python unittest that can take care of setup functionality by inheriting from TestCase, but not actually run any tests?

Sure, construct like that will surely work:

class BaseTestCase(unittest.TestCase):
    def setUp(self):
        pass  # common teardown

    def tearDown(self):
        pass  # common teardown


class ATestCase(BaseTestCase):
    def test1(self):
        pass


class BTestCase(BaseTestCase):
    def test1(self):
        pass

If knowledge from ATestCase or BTestCase is required in BaseTestCase simply override some method in subclasses but use it in superclass.

class BaseTestCase(unittest.TestCase):
    def setUp(self):
        self.instance = self._create_instance()

    def _create_instance(self):
        raise NotImplementedError()


class ATestCase(BaseTestCase):
    def _create_instance(self):
        return A()


class BestCase(BaseTestCase):
    def _create_instance(self):
        return B()

Note that if any test_(self) methods will be implemented in BaseTestCase, they'll run (and fail due to failing setUp) when discovered by automated runners.

As a workaround you may use skipTest in your setUp clause in abstract test and override it in subclasses.

class BaseTestCase(unittest.TestCase):
    def setUp(self):
        self.instance = self._create_instance()

    def _create_instance(self):
        self.skipTest("Abstract")

    def test_fromBase(self):
        self.assertTrue(True)

Note that skipping test_fromBase (eg via decorator) won't be good, since 'test should be skipped' logic will be inherited by all subclasses.

I tried Łukasz's answer and it works, but I don't like OK (SKIP=<number>) messages. For my own desires and aims for having a test suite I don't want me or someone to start trusting any particular number of skipped tests, or not trusting and digging into the test suite and asking why something was skipped, and always?, and on purpose? For me that's a non-starter.

I happen to use nosetests exclusively, and by convention test classes starting with _ are not run, so naming my base class _TestBaseClass is sufficient.

I tried this in Pycharm with Unittests and py.test and both of those tried to run my base class and its tests resulting in errors because there's no instance data in the abstract base class. Maybe someone with specific knowledge of either of those runners could make a suite, or something, that bypasses the base class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM