Using test generators to save time

Test generators are an amazing tool when you are testing small variations in the same code path. It uses generators1 which yield callables2 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.

Footnotes:

1

Generators are iterables (aka pseudo-lists) that are generated on the fly instead of all up front. wiki

2

Callables are things that you can call. In Python, this is functions and classes which define a "call" method. stack overflow