[TIP] dynamically create tests with unittest

Ben Finney ben+python at benfinney.id.au
Wed Feb 25 16:08:20 PST 2015


Albert-Jan Roskam <fomcl at yahoo.com> writes:

> With nose one can use generators to dynamically create tests:
>
> What is the preferred way to do this with unittest?

I recommend using the ‘testscenarios’ library
<URL:https://pypi.python.org/pypi/testscenarios/>:

    import unittest
    import testscenarios

    import system_under_test as sut

    class foo_func_TestCase(unittest.TestCase, testscenarios.WithScenarios):
        """ Test cases for the `foo_func` function. """

        scenarios = [
                ('empty baz', {
                    'baz': [],
                    'expected_result': "spam",
                    }),
                ('seven baz items', {
                    'baz': [3, 5, 7, 11, 13, 17, 19],
                    'expected_result': "beans",
                    }),
                ('default no baz', {
                    'expected_result': "eggs",
                    }),
                ]

        def test_returns_expected_result_given_baz(self):
            """ Should return the expected result given the `baz` value. """
            baz = getattr(self, 'baz', None)
            result = sut.foo_func(baz)
            self.assertEqual(self.expected_result, result)

        def test_quux_remains_unchanged(self):
            """ Should not affect the `quuz` value. """
            quux_prev = sut.quux
            baz = getattr(self, 'baz', None)
            sut.foo_func(baz)
            self.assertEqual(quux_prev, sut.quux)

That TestCase class will cause six text cases to be generated during the
test run: one for each combination of scenario and ‘test_*’ function.
The TestRunner output for each test case will include both the function
name and the scenario name, to make it clear which condition caused any
failure.

Each test case, when created dynamically, will have attributes as
specified by the name → value mapping for the scenario. Those attributes
can be used however the test case function chooses.

Adding new scenarios is then a simple matter of adding new entries in
the scenario collection for the class; all the test case methods will be
run with all the scenarios, as distinct test cases in the run.

-- 
 \            “Without cultural sanction, most or all of our religious |
  `\          beliefs and rituals would fall into the domain of mental |
_o__)                                 disturbance.” —John F. Schumaker |
Ben Finney




More information about the testing-in-python mailing list