Over 70 simple but incredibly effective recipes for taking control of automated testing using powerful Python testing tools
The reader can benefit from the previous article on Testing in Python using doctest.
Python provides out-of-the-box capability to put comments in code known as docstrings. Docstrings can be read when looking at the source and also when inspecting the code interactively from a Python shell. In this recipe, we will demonstrate how these interactive docstrings can be used as runnable tests.
What does this provide? It offers easy-to-read code samples for the users. Not only are the code samples readable, they are also runnable, meaning we can ensure the documentation stays up to date.
With the following steps, we will create an application combined with runnable docstring comments, and see how to execute these tests:
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.edur
>>> convert_to_basen(1, 2)
‘1/2′
>>> convert_to_basen(2, 2)
’10/2′
>>> convert_to_basen(3, 2)
’11/2’
>>> convert_to_basen(4, 2)
‘100/2’
>>> convert_to_basen(5, 2)
‘101/2’
>>> convert_to_basen(6, 2)
‘110/2’
>>> convert_to_basen(7, 2)
‘111/2’
>>> convert_to_basen(1, 16)
‘1/16’
>>> convert_to_basen(10, 16)
‘a/16’
>>> convert_to_basen(15, 16)
‘f/16′
>>> convert_to_basen(16, 16)
’10/16’
>>> convert_to_basen(31, 16)
‘1f/16′
>>> convert_to_basen(32, 16)
’20/16’
“””
import math
if __name__ == “__main__”:
import doctest
doctest.testmod()
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 with the expected output.
doctest is very picky when matching expected output with actual results.
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.
With the following steps, we will see how to use doctest to verify error conditions:
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.
>>> 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
if __name__ == “__main__”:
import doctest
doctest.testmod()
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.
I remember deciding to pursue my first IT certification, the CompTIA A+. I had signed…
Key takeaways The transformer architecture has proved to be revolutionary in outperforming the classical RNN…
Once we learn how to deploy an Ubuntu server, how to manage users, and how…
Key-takeaways: Clean code isn’t just a nice thing to have or a luxury in software projects; it's a necessity. If we…
While developing a web application, or setting dynamic pages and meta tags we need to deal with…
Software architecture is one of the most discussed topics in the software industry today, and…