As part of the function design recipe, we include one or two example calls on the
function in it's doc string. The last step of the function design
recipe is executing those function calls. Up to now we've been executing the
function calls by copying and pasting them to the Python shell and then comparing the
value returned with the value that we expect.
In this lecture you'll learn about dog test, a Python module that allows us to
run these tests in, In a more automated way.
On the right hand side of the screen there's a module named vowels.Pi that
contains 2 functions definitions, collect vowels and count vowels.
Each of those functions has two example calls on it in its doc string.
To execute the example calls we need to run the module and then copy and paste
each function call to the Python shell. Once the function call is executed we
compare the value returned with the value that we expected, to make sure that they
match. Let's do this for the other three as well.
Rather then calling each example one at a time, it would be nice to be able to run
them all at once. And Python has a module named doctest that
allows us to do just that. We begin by importing doctest and then we
call doctests function test mod, to run all the tests for this module.
What we see here are the test results. Four tests have been executed.
And in this case, all of the tests have passed.
A nice feature of doc test is that it does the comparison of the value returned by
the function call with a value that we expect automatically.
This makes the testing much less prone to human error, since we aren't doing the
comparison of those two values ourselves. Let's consider another example.
On the right hand side of the screen there's now a module named divisors, which
contains one function named to get divisors.
Get divisors has two parameters, a number and a list of possible divisors of that
number. The function returns all the items from
the list That the number can be divided evenly by.
[SOUND ]For example, for the number eight, and a list of possible divisors, one, two
and three. The function call would return a list of
divisors one and two. Eight cannot be divided evenly by three.
So 3 is not included in the list returned by the function call.
This function has another example in its stock string as well.
Let's run both of these example calls by running the module and then running doc
test. The message that we get back from doctest
this time is much longer than it was for the vowels example.
For the vowels examples, all four test cases passed.
In this case, the two example test cases were executed.
[inaudible]. And one of them failed.
A test that fails is one for which the actual value returned by the function call
doesn't match the value expected. In this case, it was the second example
call that failed. Forget divisors with the number four, and
possible divisors negative 2, 0, and two. An error occurred when executing the
function call. The error was a 0 division error.
Somewhere in our function we divided by 0. Let's look more closely at the code to see
where this would have happened. We can see from the error message that the
zero division happened on line 15 which is this if statement header.
This Boolean expression takes the number and divides it by the possible divisor to
see if it divides evenly. At this point we can look at our example.
There's the 0 in the list of possible divisors.
So that means that on line 15 we're dividing the number by 0.
Now that we've found the problem it's time to fix it.
We need to ensure that number is only divided by non-zero numbers.
To do this we'll add an additional bullion expression to our f statement as long as
the item is not equal to 0 and the number divides evenly by that item.
Will be added to the list of divisors that's returned at the end of the function
call. We call that Python evaluates the end
operation using lazy evaluation. That is, if the first operand is false,
the and expression is false and Python does not go on to valuate the second
operand to the end. In other words, when item is equal to 0.
The expression on the ride hand side of the and won't be executed.
So num won't be divided by 0. It's now time to rerun the tests.
We'll rerun the module, so we get the latest definition of this function.
And then run test mod from doc test module.
Although we no longer get the zero division error the test case still fails.
We expected to get a list with integer 2. And instead we got a two item list with
negative 2 and 2. This time there isn't a problem with the
function definition. There's a problem with the test case.
Negative 2 is the divisor of 4 and it should have been included in the list.
We'll add it now. Next we need to rerun the module and
retest it. This time, both of the test cases pass.
Instead of importing doctest and running testmod in the shell, we can do it from
the divisors module. Now each time that the divisor's module is
run, the test cases are also executed. If the test cases pass, there's no output
in the shell. No news is good news.