Interface Testing Modules in Python

I am currently learning python in preperation for a class during the summer and started by implementing various types of heaps and data structures based on priorities.

I started writing a unit test kit for a project, but ran into difficulties creating a common unit test, which only checks the interface and doesn't notice the actual implementation.

I am wondering if it is possible to do something like this.

suite = HeapTestSuite(BinaryHeap()) suite.run() suite = HeapTestSuite(BinomialHeap()) suite.run() 

What I'm doing now just feels ... wrong (multiple inheritance? ACK!) ..

 class TestHeap: def reset_heap(self): self.heap = None def test_insert(self): self.reset_heap() #test that insert doesnt throw an exception... for x in self.inseq: self.heap.insert(x) def test_delete(self): #assert we get the first value we put in self.reset_heap() self.heap.insert(5) self.assertEquals(5, self.heap.delete_min()) #harder test. put in sequence in and check that it comes out right self.reset_heap() for x in self.inseq: self.heap.insert(x) for x in xrange(len(self.inseq)): val = self.heap.delete_min() self.assertEquals(val, x) class BinaryHeapTest(TestHeap, unittest.TestCase): def setUp(self): self.inseq = range(99, -1, -1) self.heap = BinaryHeap() def reset_heap(self): self.heap = BinaryHeap() class BinomialHeapTest(TestHeap, unittest.TestCase): def setUp(self): self.inseq = range(99, -1, -1) self.heap = BinomialHeap() def reset_heap(self): self.heap = BinomialHeap() if __name__ == '__main__': unittest.main() 
+6
python unit-testing interface test-suite
source share
3 answers

I personally like the nasal test generation for this kind of thing. I would write it like this:

 # They happen to all be simple callable factories, if they weren't you could put # a function in here: make_heaps = [BinaryHeap, BinomialHeap] def test_heaps(): for make_heap in make_heaps: for checker in checkers: # we'll set checkers later yield checker, make_heap def check_insert(make_heap): heap = make_heap() for x in range(99, -1, -1): heap.insert(x) # def check_delete_min etc. checkers = [ value for name, value in sorted(globals().items()) if name.startswith('check_')] 
+4
source share

I don't think this template is terrible, but multiple inheritance is certainly not an idea.

I assume that the reason that TestHeap is not a subclass of TestCase is because it will be automatically selected and run as a test, not knowing that it should be a subclass.

I got around this problem in two other ways:

  • Instead of adding test_ functions, use write methods that are not automatically matched, and then add test () to each of your subclasses. Obviously not perfect.
  • Rewrote unittest so as not to suck, allowing __test__ = False base class. (See Testify )
+1
source share

Why not just use an alias for the class you want to test? You can write your test class related to the fake HeapImpl class, and then assign it a specific implementation before each test run:

 class TestHeap(unittest.TestCase): def setUp(self): self.heap = HeapImpl() #test cases go here if __name__ == '__main__' suite = unittest.TestLoader().loadTestsFromTestCase(TestHeap) heaps = [BinaryHeap, BinomialHeap] for heap in heaps: HeapImpl = heap unittest.TextTestRunner().run(suite) 

As long as they match the interface you use in the test suite, this should work fine. In addition, you can easily test as many implementations as you want, just add them to the heaps list.

+1
source share

All Articles