The automatic testing systemContents
IntroductionThe automatic feedback system as a teaching tool provides a number of advantages:
However, two comments about the system are important:
This pageOn this page, we look at a hypothetical task of the lab called 'demo' where students are writing a function add. We show a correct solution (i.e. a function add) to the task, and a number of incorrect solutions (each of which contains a mistake). For all of these, we show the feedback that the auto testing system would provide. In particular for the first few examples, we explain in great detail how to read the feedback from the system. The taskImagine we are given the following task:
Correct solutionA possible solution is given here: def add(a, b): """This is my add function. It returns the sum of a and b.""" return a + b There is nothing wrong with this solution. The testing system would provide a report (by email), that looks like this: Summary: Passed 1, Failed 0 ============================== Pass/fail overview ================== ok : test_add This tells us that one exercise has been tested (the exercise function was called add), and this has been tested ok. This means there were no mistakes found in that function. Most labs have more than one exercises per submission, so there will be multiple lines of pass/fail information: one for each exercise. In the following, we describe a number of mistakes and the associated error messages. Function returning wrong value (function carrying out wrong calculation)Imagine you have misunderstood the question and written the following code which computers the average value of a and b (where the sum was requested): def add(a, b): """This is my function. It returns the mean of a and b.""" return (a + b) * 0.5 The test system will provide this report: 1 Summary: Passed 0, Failed 1 2 ============================== 3 4 Pass/fail overview 5 ================== 6 7 failed : test_add 8 9 Test failure report 10 ==================== 11 12 test_add 13 -------- 14 def test_add(): 15 assert s.add(0, 0) == 0 16 > assert s.add(1, 2) == 3 17 E assert 1.5 == 3 18 E + where 1.5 = <function add at 0x838009c>(1, 2) 19 E + where <function add at 0x838009c> = s.add 20 21 test_demo.py:6: AssertionError 22 We have added line numbers to the output above to make the explanation easier:
A single failed assert statement will result in an overall fail for that exercise. Once a test has failed, no further tests will be carried out for that function. If this exercise is not assessed (i.e. students can re-submit their work), you should study the error above, try to fix the code and re-submit. In the case here, the question you should ask (to find out what is wrong) is "why does my code return 1.5 where as it should return 3 for input arguments a=1 and b=2". You can actually copy the test to Python prompt and run: >>> add(1, 2) == 3 For the code with the bug shown above, this should display: >>> add(1, 2) == 3 False where as once the bug is fixed, you should see: >>> add(1, 2) == 3 True Often, it may be more instructive to not carry out the comparison, but just display the return value, i.e. >>> add(1, 2) where the incorrect response would be: >>> add(1, 2) 1.5 and the correct answer should read: >>> add(1, 2) 3 The feedback from the testing system should help you debugging your code. Function not definedLet's consider another possible mistake. Imagine we have implemented the right code, but given the function a different name: def add_those_numbers(a, b): """This is my add function. It returns the sum of a and b.""" return a + b If we submit this, we get the following feedback: 1 Test failure report 2 ==================== 3 4 test_add 5 -------- 6 def test_add(): 7 > assert s.add(0, 0) == 0 8 E AttributeError: 'module' object has no attribute 'add' 9 10 test_demo.py:4: AttributeError
As always, the greater than sign (>) shows the line in which an assert statement has failed, and subsequent lines give more information about the type of failure. In this case, the test fails because the function that should be tested (i.e. add) appears to be missing. This kind of error will always be raised if a particular question has not been attempted. Function returning wrong data type (string)The function add needs to return the value of a+b. The type of a and b has not been specified in the instructions. We would thus expect the function to work at least for Python data types int and long (both integers), floating point numbers float and complex numbers. (Dynamic typing will ensure that the return value is of the same type as the input arguments a and b (if a and b are of the same type), and if the plus operator can deal with all the types.) Let's assume the following mistake: the function add that we submit returns the result of the calculation as a string (this may seem like a good idea but it is not: if the result of a calculation is required as a string, it can be converted into a string later): def add(a, b): """Takes numbers a and b and returns a+b.""" return str(a + b) This code would produce the following error message when being auto-tested: 1 test_add 2 -------- 3 def test_add(): 4 > assert s.add(0, 0) == 0 5 E assert '0.0' == 0 6 E + where '0.0' = <function add at 0x838009c>(0, 0) 7 E + where <function add at 0x838009c> = s.add 8 9 test_demo.py:4: AssertionError
Function returning wrong data type (list)A minor variation on Function returning wrong data type (string) is that the function returns [a + b] (which is a list with one element, and this element will be the sum of a and b) instead of a + b: def add(a, b): """Takes numbers a and b and returns a+b.""" return [a + b] The error message reads: 1 test_add 2 -------- 3 def test_add(): 4 > assert s.add(0, 0) == 0 5 E assert [0] == 0 6 E + where [0] = <function add at 0x838009c>(0, 0) 7 E + where <function add at 0x838009c> = s.add 8 9 test_demo.py:4: AssertionError The revealing line is number 5 which shows that a comparison of [0] and 0 is attempted: the list with one element ([0]) is what s.add(0,0) returned. Function not returning a valueAnother common mistake is that a function prints a value to the screen rather than returning it to the calling level using the return command. Suppose our function would print the value of a+b instead of returning it: def add(a, b): """Takes numbers a and b and returns a+b.""" print(a + b) The error report would read: 1 test_add 2 -------- 3 def test_add(): 4 > assert s.add(0, 0) == 0 5 E assert None == 0 6 E + where None = <function add at 0x838009c>(0, 0) 7 E + where <function add at 0x838009c> = s.add 8 9 test_demo.py:4: AssertionError 10 ------------------------------- Captured stdout ------------------------------- 11 0
Function not having a docstringSuppose the function is implemented correctly, but no docstring has been provided: def add(a, b): return a + b The error message reads: 1 test_add 2 -------- 3 def test_add(): 4 assert s.add(0, 0) == 0 5 assert s.add(1, 2) == 3 6 assert s.add(0, 1) == 1 7 assert s.add(1, 1) == 2 8 assert s.add(1. 5, 1.) == 2.5 9 10 #Does the function have a documentation string? 11 > assert s.add.__doc__ != None 12 E assert <function add at 0x838009c>.__doc__ != None 13 E + where <function add at 0x838009c> = s.add 14 15 test_demo.py:11: AssertionError We observe that
Occasionally, assert statements are preceded by Python comments in the line above (as here where the comment is in line 10 and the assert statement in line 11). These comments have been placed there to help understanding what is being tested: they are worth reading -- often there is no need to look into the detailed error message if that line provides enough context, or at least knowing about the context will make understanding the purpose of the assert statement easier. When the source code file has syntax errorsThe testing system will try first import the student file under the name s. I.e. if the the submitted file is demo.py, then the testing file will want to run a command like: import demo as s If there are syntax errors in the demo.py file, this will be impossible, and the testing cannot even be started. In this case, an email along these lines is returned: Test failure report ==================== import s.py ----------- When trying to import your submission, we have encountered an error, and as a result, this submission has failed. A likely problem is indentation. You should find that Python reports some error (SyntaxError most likely) when you execute your file MYFILE *before* submission (either by pressing F5 in IDLE, or running "python.exe MYFILE.py"). As the text says, the best way to avoid/fix this, is to make sure that the file is valid Python, i.e. executing it does not raise any error messages. Writing code is easyFinally, please do ask for help in interpreting error messages (both from the testing system and those that your code produces as you do the exercises): the error messages you receive in the feedback are (slightly enhanced) standard Python error messages. Learning how to read those will benefit fit you far beyond this course. This goes back to the saying that "writing code is easy -- debugging it is hard". |
|