Course 3.2Lesson 3 of 5
Most bugs live at the edges: the empty input, a single item, repeats, items that are all equal, the ends of a range, and strange values such as zero and negative numbers. A function that works for the usual cases can fail on all of them. List the edge cases before you test, and test each. When a trusted answer exists, such as Python's own sorted, test with many random inputs from a fixed seed and compare the two, which finds bugs that nobody thought of and returns the first failing input. Properties that must always hold, such as the result being in order, having the same length and the same items, can be checked with assert for every random input. Assert inside a function can also check the thinking of the code.
Try the code and the simulations beside the lesson.
After this lesson you can
Think about a function that gives the second largest number of a list. You try [5, 9, 2] and get 5. Right. You try [1, 2, 3, 4] and get 3. Right. It works! But does it?
Predict first. Which of the seven cases will fail? Then run it.
The function sorts the list from the biggest, and takes the item at position 1. For the usual cases, it is right. But look at what you did not think of.
[9, 9, 3]. The sorted list is [9, 9, 3], and position 1 is 9. But the second largest different number is 3. A bug, if we want the second largest value.[5, 5, 5]. There is no second largest. What should the function say? The test says None.[8] and [] have no second item. The code raises an IndexError.Four of the seven cases fail. The fixed version works with set (which drops the repeats) and checks the length before taking position 1. All seven cases pass.
For almost any function, before you test, go through this list and ask: what does my function do for...
| Edge | Examples |
|---|---|
| nothing | empty list, empty text, 0 |
| one item | a list of one, a one-letter text |
| two items | the smallest list with an order |
| repeats | [3, 3, 3], a text with a doubled letter |
| all equal | everything the same |
| the ends of a range | the first and the last allowed value, and one past each |
| already in order, or in reverse order | for sorting and searching |
| strange values | negative, zero, very big, a decimal where a whole number is expected |
This list finds more bugs than any amount of testing with ordinary values.
You cannot think of every case. A computer can try thousands. The method: make many random inputs, and compare the function with a trusted answer: a different way to compute the same thing that you know is right, such as Python's own sorted.
Comparing with a trusted answer. my_sort is an insertion sort with a hidden bug: it drops the last item of a list that has more than 4 items. first_failure makes 200 random lists (sizes 0 to 8, values 0 to 20), and compares my_sort(data) with sorted(data). It returns the first input where they differ. You see the exact input that breaks the function. For the correct function, sorted, it returns None: no failure.
Note random.seed(7). A seed makes the "random" inputs the same every time, so that a failure can be reproduced. A bug that appears sometimes and cannot be repeated is very hard to fix. The seed is the cure.
Properties. Sometimes there is no trusted answer, but there are things that must always be true. For a sort:
check_properties tests all three on 100 random lists with assert. For the buggy sort, the first property fails: "the length changed". Properties are a powerful way to test: you state what must be true, and the computer looks for a counter-example.
Random tests are a net, not a proof. The edge cases on the checklist are still the first tests to write.
assert is also good inside a function, to check your own thinking, as the next program shows.
Start with two quick questions. Each New numbers gives you a fresh one, so you can practise as long as you like.
Then the labs and the problems:
assert inside a function checks the thinking of the code.Try each one on your own first. If you are stuck, open a hint. Then check with Show the answer.
second_largest([9, 9, 3]) give in the buggy version, and what should it give?Every lesson is open to read. Enrolling also lets you:
Log in to join the discussion.
Loading…
This lesson is free to read. Enroll free to keep your place and take the tests.