...

/

“Halt And Catch Fire”

“Halt And Catch Fire”

We'll cover the following...

It is not enough to test that functions succeed when given good input; you must also test that they fail when given bad input. And not just any sort of failure; they must fail in the way you expect.

Press + to interact
import roman1
print (roman1.to_roman(4000))
#MMMM
print (roman1.to_roman(5000))
#MMMMM
print (roman1.to_roman(9000)) #①
#MMMMMMMMM

① That’s definitely not what you wanted — that’s not even a valid Roman numeral! In fact, each of these numbers is outside the range of acceptable input, but the function returns a bogus value anyway. Silently returning bad values is baaaaaaad; if a program is going to fail, it is far better if it fails quickly and noisily. “Halt and catch fire,” as the saying goes. The Pythonic way to halt and catch fire is to raise an exception.

The Pythonic way to halt and catch fire is to raise an exception.

The question to ask yourself is, “How can I express this as a testable requirement?” How’s this for starters:

The to_roman() function should raise an OutOfRangeError when given an integer greater than 3999.

What would that test look like?

Press + to interact
import unittest
import roman2
class ToRomanBadInput(unittest.TestCase): #①
def test_too_large(self): #②
'''to_roman should fail with large input'''
self.assertRaises(roman2.OutOfRangeError, roman2.to_roman, 4000) #③

① Like the previous test case, you create a class that inherits from unittest.TestCase. You can have more than one test per class (as you’ll see later in this chapter), but I chose to create a new class here because this ...