Download Assertions, Documentation and DocTest

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
LAB
SIXTEEN
Assertions, Documentation and
DocTest
16.1
Walkthrough: Assertions
Assertions are designed to test for conditions in programs and cause the program to terminate with an error message if the expression is false. Assertions are used to implement defensive programming, such as pre-conditions,
post-conditions and loop invariants.
In Python, the assert statement throws an exception AssertionError if the conditional expression is False:
1
2
3
4
5
>>> assert 1 > 2
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AssertionError
>>>
This form of the assert statement is not particularly helpful because it doesn’t say what went wrong. assert
can take a second expression (separated by a comma) which is printed out when the exception occurs:
1
2
3
4
5
>>> assert 1 > 2, "Houston, we have a problem!"
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AssertionError: Houston, we have a problem
>>>
You can also include the variables in the assert conditional expression:
1
2
3
4
5
6
>>> count = 5
>>> assert count > 10, "count must be greater than 10, but has value %s" % count
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AssertionError: count must be greater than 10, but has value 5
>>>
Now, let’s use assertions to check the pre-conditions on a function greet, which greets the user n times:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>>> def greet(n):
... assert n >= 0, "the number of greetings n must be non-negative"
... for i in range(n):
...
print 'Hi there!'
...
>>> greet(3)
Hi there!
Hi there!
Hi there!
>>> greet(-1)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 2, in greet
AssertionError: the number of greetings n must be non-negative
>>>
INFO1903: Informatics (Adv)
1
LAB SIXTEEN
INFO1903: Informatics (Adv)
Many people consider assertions to be primarily for debugging purposes rather than something which should stay
in the code all of the time. However, rather than remove the assert statements (which might accidently introduce
bugs from typos etc, we may want to just ignore them. To support this, Python has the special variable __debug__
which is set when the interpreter starts up. If python is started with the -O or -OO options, then __debug__ is set
to false, and all assert statements are ignored.
16.1.1
Exercise
Write a function called bound which takes three arguments, minval, value and maxval. It should return value
if the value ≥ minval and ≤ maxval. Otherwise it should return either minval if value < minval and maxval
if value > maxval.
You should write this function, test to make sure it is correct with some sensible test cases. To help you out, we
have given you the first one:
1
2
3
>>> bound(0, 5, 10)
5
>>>
Also, you need to write a sensible pre-condition and post-condition for this function. The pre-condition should
check that the minval and maxval arguments have sensible values, and the post-condition should check that the
function is doing what it says it does.
16.2
Walkthrough: Python documentation
Every Python function and module has documentation built into the source code. You can access this documentation using the help function:
1
2
>>> help(abs)
Help on built-in function abs in module __builtin__:
3
4
5
abs(...)
abs(number) -> number
6
Return the absolute value of the argument.
7
8
>>>
This documentation is stored in a special Python attribute called __doc__ which is a string containing the documentation:
1
2
3
>>> abs.__doc__
'abs(number) -> number\n\nReturn the absolute value of the argument.'
>>>
This documentation attribute is set if a triple quoted string appears between the def line of the function declaration
and the function’s body:
1
2
3
4
5
6
7
8
>>> def mult(x, y):
... """mult(number, number) -> number
...
...
This function multiplies two numbers together and returns
...
the result"""
... return x*y
...
>>>
Again, we can see this help using help:
1
2
>>> help(mult)
Help on function mult in module __main__:
3
4
5
mult(x, y)
mult(number, number) -> number
6
James Curran and Tara Murphy
2
LAB SIXTEEN
This function multiplies two numbers together and returns
the result
7
8
9
INFO1903: Informatics (Adv)
>>>
and also using the __doc__ attribute:
1
2
3
>>> mult.__doc__
'mult(number, number) -> number\n\nThis function multiplies two numbers ... the result'
>>>
16.2.1
Exercise
Write the Python documentation for the bound method you wrote in the previous exercise. This should say what
the function does, including the purpose of the three arguments, and what the pre-conditions are.
16.3
DocTest
Python has a clever way of implementing unit tests that have been written into the documentation. There is a
module called doctest which extracts the documentation from all of the functions and classes in a module, finds
test cases within the documentation and then runs the test cases, checking the output matches the expected output.
Like all modules, there is extensive documentation both in the builtin help help(doctest) and also in the online
Python documentation http://docs.python.org/lib/module-doctest.html.
For this lab exercise, we would like to see how well you interpret the standard documentation (rather than our
helpful walkthroughs). So, go to the URL given above and follow the documentation through for doctest. When
you have finished reading the online documentation, try writing some doctests for the mult function above.
To help you out, we will write one out for mult and test it out:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>>
...
...
...
...
...
...
...
...
>>>
>>>
>>>
(0,
>>>
def mult(x, y):
"""mult(number, number) -> number
returns the product of the two numbers x and y
>>> mult(5, 5)
25
"""
return x*y
import doctest
doctest.testmod()
1)
Like all good regression tests, this doesn’t print anything out about which tests have been passed, it only prints
something out if the tests fail. The two numbers returned in the tuple are the number of tests that failed and the
total number of tests.
16.3.1
Exercise
Write the doctests for the bound function you have defined and documented above. They should test the boundary
conditions and also that the pre-conditions are working correctly.
16.4
Capability checklist
When you’ve finished this lab, check that you know how to. . .
1. write assertions for defensive programming
2. write Python documentation for your own functions
3. write doctest unit tests inside your Python documentation
If you don’t know how to do any of these things once you have completed the lab, please come and ask us.
James Curran and Tara Murphy
3