Corner cases will appear as we continue to develop our code. By capturing corner cases in an iterable list, there is less code to write and capture another test scenario. This can increase our efficiency at testing new scenarios.
recipe23.py
and use it to store all our code for this recipe.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)
def convert_to_basen(value, base): """Convert a base10 number to basen. Base 2 >>> inputs = [(1,2,'1/2'), (2,2,'11/2')] >>> for value,base,expected in inputs: ... actual = convert_to_basen(value,base) ... assert actual == expected, 'expected: %s actual: %s' % (expected, actual) >>> convert_to_basen(0, 2) Traceback (most recent call last): ... ValueError: math domain error Base 36. >>> inputs = [(1,36,'1/36'), (35,36,'z/36'), (36,36,'10/36')] >>> for value,base,expected in inputs: ... actual = convert_to_basen(value,base) ... assert actual == expected, 'expected: %s actual: %s' % (expected, value) >>> convert_to_basen(0, 36) Traceback (most recent call last): ... ValueError: math domain error """ import math
if __name__ == "__main__": import doctest doctest.testmod()
In the previous screenshot, the key information is on this line: AssertionError: expected: 11/2 actual: 10/2. Is this test failure a bit contrived? Sure it is. But seeing a test case shows useful output is not. It's important to verify that our tests give us enough information to fix either the tests or the code.
We created an array with each entry containing both the input data as well as the expected output. This provides us with an easy way to glance at a set of test cases.
Then, we iterate over each test case, calculate the actual value, and run it through a Python assert
. An important part that is needed is the custom message 'expected: %s actual: %s'
. Without it, we would never get the information to tell us which test case failed.
Here are some criteria that are worth considering when deciding whether to put these tests in doctest
:
If there is little value in having this in the documentation, and if it clutters the code, then that is a strong hint that this test block belongs to a separate test module.
Testing corner cases by iteration section of Chapter 1
18.221.254.61