[TIP] dynamically create tests with unittest
Malini Kamalambal
malini.kamalambal at RACKSPACE.COM
Thu Feb 26 03:31:14 PST 2015
On 2/25/15 7:08 PM, "Ben Finney" <ben+python at benfinney.id.au> wrote:
>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
ddt is another good option.
See docs here http://ddt.readthedocs.org/en/latest/
Rewriting Ben's example with ddt would looks something like below.
import unittest
import ddt
import system_under_test as sut
@ddt.ddt
class foo_func_TestCase(unittest.TestCase):
""" Test cases for the `foo_func` function. """
@ddt.data([], [3, 5, 7, 11, 13, 17, 19])
def test_returns_expected_result_given_baz(self, baz):
""" Should return the expected result given the `baz` value.
"""
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)
Regards,
Malini
More information about the testing-in-python
mailing list