Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
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