1

How can I create multiple TestCases and run them programmatically? I'm trying to test multiple implementations of a collection on a common TestCase.

I'd prefer to stick to with plain unittest and avoid dependencies.

Here's some resources that I looked at that didn't quite meet what I wanted:

Here's a minimal (non)working example.

import unittest

MyCollection = set
AnotherCollection = set
# ... many more collections


def maximise(collection, array):
    return 2


class TestSubClass(unittest.TestCase):

    def __init__(self, collection_class):
        unittest.TestCase.__init__(self)
        self.collection_class = collection_class
        self.maximise_fn = lambda array: maximise(collection_class, array)


    def test_single(self):
        self.assertEqual(self.maximise_fn([1]), 1)


    def test_overflow(self):
        self.assertEqual(self.maximise_fn([3]), 1)

    # ... many more tests


def run_suite():
    suite = unittest.defaultTestLoader
    for collection in [MyCollection, AnotherCollection]:
        suite.loadTestsFromTestCase(TestSubClass(collection))
    unittest.TextTestRunner().run(suite)


def main():
    run_suite()


if __name__ == '__main__':
    main()

The above approach errors with in loadTestsFromTestCase:

TypeError: issubclass() arg 1 must be a class

Community
  • 1
  • 1
Joe
  • 3,370
  • 4
  • 33
  • 56

1 Answers1

1

How about using pytest with to parametrize fixture:

import pytest

MyCollection = set
AnotherCollection = set


def maximise(collection, array):
    return 1

@pytest.fixture(scope='module', params=[MyCollection, AnotherCollection])
def maximise_fn(request):
    return lambda array: maximise(request.param, array)

def test_single(maximise_fn):
    assert maximise_fn([1]) == 1

def test_overflow(maximise_fn):
    assert maximise_fn([3]) == 1

If that's not an option, you can make a mixin to contain test function, and subclasses to provide maximise_fns:

import unittest

MyCollection = set
AnotherCollection = set


def maximise(collection, array):
    return 1


class TestCollectionMixin:
    def test_single(self):
        self.assertEqual(self.maximise_fn([1]), 1)

    def test_overflow(self):
        self.assertEqual(self.maximise_fn([3]), 1)


class TestMyCollection(TestCollectionMixin, unittest.TestCase):
    maximise_fn = lambda self, array: maximise(MyCollection, array)


class TestAnotherCollection(TestCollectionMixin, unittest.TestCase):
    maximise_fn = lambda self, array: maximise(AnotherCollection, array)


if __name__ == '__main__':
    unittest.main()
Joe
  • 3,370
  • 4
  • 33
  • 56
falsetru
  • 357,413
  • 63
  • 732
  • 636
  • Nice, the mixin idea is about perfect. It's a little repetitive but very clear. – Joe Dec 23 '15 at 17:15
  • The CPython test suite uses the mixin approach to test, for instance, C and Python implementations or, for instance, tests common to more than one class, such as unicode and bytes or tuples and lists (and even range) or sets and frozensets. – Terry Jan Reedy Dec 23 '15 at 19:47