Free delivery stopped working
A customer spends exactly 50 pounds. The site promised free delivery at 50 pounds. It charged her 3.99 anyway.
Somebody changed one character last week. Nobody noticed, because nothing checked it. A test is a small piece of code that would have noticed.
By the end of this lesson
Note
I can write a test that checks a function.
Key words
| Word | What it means | Example |
|---|---|---|
| Test | code that checks other code gives the right answer | |
| Assert | a line that stops with an error if something is false | assert fee == 0 |
| Expected | the answer the function should give | |
| Actual | the answer the function really gives | |
| Edge case | a value at a limit, where bugs often hide | 5000 |
The cells students fill in are left blank in this preview.
A test compares expected and actual
Every test asks one question: does the function give the answer it should?
You write down the expected answer. You run the function to get the actual answer. Then assert compares them.
If they match, nothing happens and the test passes. If they differ, Python stops with an AssertionError.
Try it: a first test
def delivery_fee(total):
# Prices are in pence. Orders of 5000 pence (50 pounds) or more go free.
if total >= 5000:
return 0
return 399
expected = 399
actual = delivery_fee(1200)
print("Expected:", expected, "Actual:", actual)
assert actual == expected
print("Test passed")
Test the edges, not only the middle
A test with 1200 pence and a test with 9000 pence both pass, even with a bug. Bugs hide at the edge: the exact value where the rule changes.
For "free at 50 pounds", test just under, exactly on, and just over the limit.
Worked example: tests for free delivery
| Order (pence) | Why this value | Expected fee | With the > bug |
|---|---|---|---|
| 1200 | An ordinary small order | 399 | 399, passes |
| 4999 | One penny under the limit | 399 | 399, passes |
| 5000 | Exactly on the limit | 0 | 399, fails |
| 9000 | An ordinary large order | 0 | 0, passes |
The cells students fill in are left blank in this preview.
A common mistake
Warning
Many people think a passing test proves the code is right. A test only checks the values you chose. If you never try the edge, a bug at the edge passes every test.
Practise: catch the bug at the edge
def delivery_fee(total):
# Somebody changed >= to > by mistake.
if total > 5000:
return 0
return 399
assert delivery_fee(1200) == 399
print("Small order: passed")
assert delivery_fee(9000) == 0
print("Large order: passed")
# Add one more assert for an order of exactly 5000 pence.
# What should the fee be? Press Run and read what happens.
Tests live in functions named test_
At work, each test is its own function whose name starts with test_. A test runner such as pytest finds them all and runs them.
One function checks one idea. Its name says the idea: test_exactly_five. When it fails, the name tells you what broke.