Chaining together a suite of tests

Unittest makes it easy to chain together test cases into a TestSuite. A TestSuite can be run just like a TestCase, but it also provides additional functionality to add a single test, multiple tests, and count them.

Why do we need this? Chaining together tests into a suite gives us the ability to pull together more than one module of test cases for a test run, as well as picking and choosing a subset of test cases. Up until now, we have generally run all the test methods from a single class. TestSuite gives us an alternative means to define a block of testing.

How to do it...

In the following steps, we will code multiple test case classes, and then load their test methods into suites so we can run them.

  1. Create a new file named recipe5.py in which to put our sample application and test cases.
  2. Pick a class to test. In this case, we will use our Roman numeral converter.
    class RomanNumeralConverter(object):
      def __init__(self):
        self.digit_map = {"M":1000, "D":500, "C":100, "L":50, "X":10, "V":5, "I":1}
    
      def convert_to_decimal(self, roman_numeral):
        val = 0
        for char in roman_numeral:
          val += self.digit_map[char]
        return val
  3. Create two test classes with various test methods spread between them.
    import unittest
    
    class RomanNumeralConverterTest(unittest.TestCase):
      def setUp(self):
        self.cvt = RomanNumeralConverter()
    
      def test_parsing_millenia(self):
        self.assertEquals(1000, 
                 self.cvt.convert_to_decimal("M"))
    
      def test_parsing_century(self):
        self.assertEquals(100, 
                 self.cvt.convert_to_decimal("C"))
    
    
    class RomanNumeralComboTest(unittest.TestCase):
      def setUp(self):
        self.cvt = RomanNumeralConverter()
    
      def test_multi_millenia(self):
        self.assertEquals(4000, 
                 self.cvt.convert_to_decimal("MMMM"))
    
      def test_multi_add_up(self):
        self.assertEquals(2010, 
                 self.cvt.convert_to_decimal("MMX"))
  4. Create a test runner in a separate file named recipe5_runner.py that pulls in both test cases.
    if __name__ == "__main__":
      import unittest
      from recipe5 import *
    
      suite1 = unittest.TestLoader().loadTestsFromTestCase( 
                     RomanNumeralConverterTest)
      suite2 = unittest.TestLoader().loadTestsFromTestCase( 
                     RomanNumeralComboTest)
      suite = unittest.TestSuite([suite1, suite2])
      unittest.TextTestRunner(verbosity=2).run(suite)
  5. Execute the test runner, and observe how tests are pulled in from both test cases.
    How to do it...

How it works...

The unittest module provides a convenient way to find all the test methods in a TestClass and bundle them together as a suite using its loadTestsFromTestCase. To further the usage of test suites, we are able to combine these two suites together as a single suite using unittest.TestSuite([list...]). The TestSuite class is designed to act like a TestCase class, even though it doesn't subclass TestClass, allowing us to run it using TextTestRunner. This recipe shows the verbosity turned up, allowing us to see exactly which test methods were run, and which test case they came from.

There's more...

In this recipe, we ran the tests from a different file from where the test cases are defined. This is different from the previous recipes where the runnable code and the test case were contained in the same file. Since the runner is defining the tests we run, we can easily create more runners that combine different suites of tests.

Name of the test case should be significant

In the previous recipes, it has been advised to name the test case as [class under test]Test. This is to make it apparent to the reader that the class under test and the related test share an important relationship. Now that we are introducing another test case, we need to pick a different name. The name should explain clearly why these particular test methods are split out into a separate class. For this recipe, the methods are split out to show more complex combinations of Roman numerals.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.20.231