开发者

How to run the same test-case for different classes?

开发者 https://www.devze.com 2023-01-27 20:55 出处:网络
I have开发者_JAVA技巧 several classes that share some invariants and have a common interface, and I would like to run automatically the same test for each of them.

I have开发者_JAVA技巧 several classes that share some invariants and have a common interface, and I would like to run automatically the same test for each of them.

As an example, suppose I have several classes that implement different approaches for partitioning a data-set. The common invariant here would be, that for all of these classes the union over all partitions should equal the original data-set.

What I currently have looks something like this:

class PartitionerInvariantsTests(unittest.TestCase):
    def setUp(self):
        self.testDataSet = range(100) # create test-data-set

    def impl(self, partitioner):
        self.assertEqual(self.testDataSet, 
                         chain.from_iterable(partitioner(self.testDataSet))

Then I add a different function that calls impl for each of the classes I want to test with an instance of that class. The problem with this becomes apparent when doing this for more than one test-function. Suppose I have 5 test-functions and 5 classes I want to test. This would make 25 functions that look almost identical for invoking all the tests.

Another approach I was thinking about was to implement the template as a super-class, and then create a sub-class for each of the classes I want to test. The sub-classes could provide a function for instantiating the class. The problem with that is that the default test-loader would consider the (unusable) base-class a valid test-case and try to run it, which would fail.

So, what are your suggestions?

P.S.: I am using Python 2.6


You could use multiple inheritance.

class PartitionerInvariantsFixture(object):
    def setUp(self):
        self.testDataSet = range(100) # create test-data-set
        super(PartitionInvariantsFixture, self).setUp()

    def test_partitioner(self):
        TestCase.assertEqual(self.testDataSet, 
                     chain.from_iterable(self.partitioner(self.testDataSet))

class MyClassTests(TestCase, PartitionerInvariantsFixture):
    partitioner = Partitioner


Subclass PartitionerInvariantsTests:

class PartitionerInvariantsTests(unittest.TestCase):
    def test_impl(self):
        self.assertEqual(self.testDataSet, 
                         chain.from_iterable(self.partitioner(self.testDataSet))

class PartitionerATests(PartitionerInvariantsTests):

for each Partitioner class you wish to test. Then test_impl would be run for each Partitioner class, by virtue of inheritance.

Following up on Nathon's comment, you can prevent the base class from being tested by having it inherit only from object:

import unittest

class Test(object):
    def test_impl(self):
        print('Hi')

class TestA(Test,unittest.TestCase):
    pass

class TestB(Test,unittest.TestCase):
    pass

if __name__ == '__main__':
    unittest.sys.argv.insert(1,'--verbose')
    unittest.main(argv = unittest.sys.argv)    

Running test.py yields

test_impl (__main__.TestA) ... Hi
ok
test_impl (__main__.TestB) ... Hi
ok

----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK
0

精彩评论

暂无评论...
验证码 换一张
取 消