Test generators are an amazing tool when you are testing small variations in the same code path. It uses generators[fn:0] which yield callables[fn:1] that are called as the test suite runs. For example, imagine you’re testing a rounding library.
class TestRound(object):
def _check_rounding(self, test, expected):
assert round(test) == expected
def test_rounding(self):
for x, y in [(1, 1),
(1.9, 2)]:
yield self._check_rounding, x, y
# VERSUS
class TestRound(unittest.TestCase):
def test_rounding_same(self):
self.assertEquals(round(1), 1)
def test_rounding_one_dot_nine_to_two(self):
self.assertEquals(round(1.9), 2)
While these two examples look mostly similar for 2 cases, imagine what ten cases would look like, or 50. For a much more real-world example, imagine a test generator which will crawl your webapp’s url routing setup and assert that each of them return a 200 status code.
There is support for test generators in both nose and unittest2. I’ve outlined examples of both in a small git repository on github.
[fn:0] Generators are iterables (aka pseudo-lists) that are generated on the fly instead of all up front. wiki
[fn:1] Callables are things that you can call. In Python, this is functions and classes which define a “call” method. stack overflow