Search code examples
pythontddunit-testing

Python library 'unittest': Generate multiple tests programmatically


Possible Duplicate:
How do you generate dynamic (parameterized) unit tests in Python?

I have a function to test, under_test, and a set of expected input/output pairs:

[
(2, 332),
(234, 99213),
(9, 3),
# ...
]

I would like each one of these input/output pairs to be tested in its own test_* method. Is that possible?

This is sort of what I want, but forcing every single input/output pair into a single test:

class TestPreReqs(unittest.TestCase):

    def setUp(self):
        self.expected_pairs = [(23, 55), (4, 32)]

    def test_expected(self):
        for exp in self.expected_pairs:
            self.assertEqual(under_test(exp[0]), exp[1])

if __name__ == '__main__':
    unittest.main()

(Also, do I really want to be putting that definition of self.expected_pairs in setUp?)

UPDATE: Trying doublep's advice:

class TestPreReqs(unittest.TestCase):

    def setUp(self):
        expected_pairs = [
                          (2, 3),
                          (42, 11),
                          (3, None),
                          (31, 99),
                         ]

        for k, pair in expected_pairs:
            setattr(TestPreReqs, 'test_expected_%d' % k, create_test(pair))

    def create_test (pair):
        def do_test_expected(self):
            self.assertEqual(get_pre_reqs(pair[0]), pair[1])
        return do_test_expected


if __name__ == '__main__':
    unittest.main()

This does not work. 0 tests are run. Did I adapt the example incorrectly?


Solution

  • Not tested:

    class TestPreReqs(unittest.TestCase):
        ...
    
    def create_test (pair):
        def do_test_expected(self):
            self.assertEqual(under_test(pair[0]), pair[1])
        return do_test_expected
    
    for k, pair in enumerate ([(23, 55), (4, 32)]):
        test_method = create_test (pair)
        test_method.__name__ = 'test_expected_%d' % k
        setattr (TestPreReqs, test_method.__name__, test_method)
    

    If you use this often, you could prettify this by using utility functions and/or decorators, I guess. Note that pairs are not an attribute of TestPreReqs object in this example (and so setUp is gone). Rather, they are "hardwired" in a sense to the TestPreReqs class.