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

1 Answer 1

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()
Sign up to request clarification or add additional context in comments.

2 Comments

Nice, the mixin idea is about perfect. It's a little repetitive but very clear.
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.