Catching stack traces

It's a common fallacy to write tests only for successful code paths. We also need to code against error conditions including the ones that generate stack traces. With this recipe, we will explore how stack traces are pattern-matched in doc testing that allows us to confirm expected errors.

How to do it...

With the following steps, we will see how to use doctest to verify error conditions:

  1. Create a new file called recipe17.py to write all our code for this recipe.
  2. Create a function that converts base 10 numbers to any other base using recursion.
    def convert_to_basen(value, base):
        import math
    
        def _convert(remaining_value, base, exp):
            def stringify(value):
                if value > 9:
                    return chr(value + ord('a')-10)
                else:
                    return str(value)
    
            if remaining_value >= 0 and exp >= 0:
                factor = int(math.pow(base, exp))
                if factor <= remaining_value:
                    multiple = remaining_value / factor
                    return stringify(multiple) + 
                      _convert(remaining_value-multiple*factor, 
                                    base, exp-1)
                else:
                    return "0" + 
                           _convert(remaining_value, base, exp-1)
            else:
                return ""
    
        return "%s/%s" % (_convert(value, base, 
                             int(math.log(value, base))), base)
  3. Add a docstring just below the external function declaration that includes two examples that are expected to generate stack traces.
    def convert_to_basen(value, base):
        """Convert a base10 number to basen.
    
        >>> convert_to_basen(0, 2)
        Traceback (most recent call last):
            ...
        ValueError: math domain error
    
        >>> convert_to_basen(-1, 2)
        Traceback (most recent call last):
            ...
        ValueError: math domain error
        """
        import math
  4. Add a test runner block that invokes Python›s doctest module.
    if __name__ == "__main__":
        import doctest
        doctest.testmod()
  5. Run the code from the command line. In the following screenshot, notice how nothing is printed. This is what happens when all the tests pass.
    How to do it...
  6. Run the code from the command line with -v to increase verbosity. In the next screenshot, we can see that 0 and -1 generate math domain errors. This is due to using math.log to find the starting exponent.
    How to do it...

How it works...

The doctest module looks for blocks of Python inside docstrings and runs it like real code. >>> is the same prompt we see when we use the interactive Python shell. The following line shows the expected output. doctest runs the statements it sees and then compares the actual output with the expected output.

With regard to stack traces, there is a lot of detailed information provided in the stack trace. Pattern matching the entire trace is ineffective. By using the ellipsis, we are able to skip the intermediate parts of the stack trace and just match on the distinguishing part: ValueError: math domain error.

This is valuable, because our users can see not only the way it handles good values, but will also observe what errors to expect when bad values are provided.

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

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