Testing Your Code Semiautomatically

In Designing New Functions: A Recipe, we introduced the function design recipe (FDR). Following the FDR, the docstrings that we write include example function calls.

The last step of the FDR involves testing the function. Up until now, we have been typing the function calls from the docstrings to the shell (or copying and pasting them) to run them and then have been comparing the results with what we expect to make sure they match.

Python has a module called doctest that allows us to run the tests that we include in docstrings all at once. It reports on whether the function calls return what we expect. We will use doctest to run the tests from module temperature_program from Selecting Which Code Gets Run on Import: __main__ :

images/modules/doctest_success.png

That message tells us that three tests were run and none of them failed. That is, the three function calls in the docstrings were run, and they returned the same value that we expected and stated in the docstring.

Now let’s see what happens when there is an error in our calculation. Instead of the calculation we’ve been using, (fahrenheit - 32.0) * 5.0 / 9.0, let’s remove the parentheses: fahrenheit - 32.0 * 5.0 / 9.0.

images/modules/temperature_program_bug.png

Here is the result of running doctest on that module:

images/modules/doctest_failure.png

The failure message above indicates that function call convert_to_celsius(75) was expected to return 23.88888888888889, but it actually returned 57.22222222222222. The other two tests ran and passed.

When a failure occurs, we need to review our code to identify the problem. We should also check the expected return value listed in the docstring to make sure that the expected value matches both the type contract and the description of the function.