Every time Rocket changes the fuel function, he runs it, types three distances, and checks each answer against his notebook. It takes five minutes each time.
"I changed one tiny thing," he says, "and I still have to check everything again. By hand. Every single time."
Raven turns to a page with three rows: input and expected answer. "What do you notice?" she asks. "These checks never change. Only the function changes."
Nova glows green, then red, then green again. "I found a pattern," she says. "Write each check as one line of code. Python runs them all in a blink and tells you if one fails."
Rocket types the word assert for the first time.
assert followed by a condition checks it. If the condition is True, nothing happens and the program carries on. If it is False, the program stops with an AssertionError.
A test case is an input with the answer you expect, worked out by hand. You can add a message after a comma to explain a failure.
# test_fuel.py
def fuel_needed(distance, rate=3, reserve=10):
return distance * rate + reserve
def test_fuel_needed():
assert fuel_needed(20) == 70
assert fuel_needed(0) == 10, "zero distance still needs the reserve"
assert fuel_needed(20, 4) == 90
assert fuel_needed(20, reserve=0) == 60
test_fuel_needed()
print("All tests passed") All tests passed
Now suppose someone changes the reserve default from 10 to 5 by mistake. The tests catch it straight away:
# test_fuel_fail.py (reserve changed to 5 by mistake)
def fuel_needed(distance, rate=3, reserve=5):
return distance * rate + reserve
def test_fuel_needed():
assert fuel_needed(20) == 70
test_fuel_needed()
print("All tests passed") Traceback (most recent call last):
File "test_fuel_fail.py", line 8, in <module>
test_fuel_needed()
File "test_fuel_fail.py", line 6, in test_fuel_needed
assert fuel_needed(20) == 70
AssertionError assert works directly with a function that returns a bool. Use assert not to check that something is False.
Good tests include the edges: zero, negative numbers and the smallest cases.
# test_is_even.py
def is_even(n):
return n % 2 == 0
def test_is_even():
assert is_even(4)
assert not is_even(7)
assert is_even(0)
assert is_even(-2)
test_is_even()
print("All tests passed") | Statement | True or false? |
|---|---|
| assert True does nothing and the program carries on. | ? |
| assert False stops the program with an AssertionError. | ? |
| A test should compare against an answer worked out by hand. | ? |
| assert fuel_needed(20) == fuel_needed(20) is a useful test. | ? |
Tests turn five minutes of checking into one keypress. Tomorrow you will test a module from a separate test file and catch a real bug.