← Back to course
Code Crew G6+ / Week 10 / Thursday
4/6
Week 10 Β· Bugs and tests

Thursday

Tests with assert
// Tracebacks, try and except, and assert
⏱ about 30 min

Thursday: Tests with assert

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

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
With reserve=5, what does fuel_needed(20) actually return?
Was All tests passed printed? (yes or no)
GOOD TEST CASES
  • Read the question.
  • Tap your answer.
Which is the best extra test for fuel_needed?
Why test fuel_needed(0)?
At your computer
1. Type test_fuel.py, save it and run it. You should see All tests passed.
2. Change reserve=10 to reserve=5 in the def line. Run it and read the AssertionError.
3. Change it back. Add your own test: assert fuel_needed(1) == 13.
4. Add a test with a message after a comma, then break it on purpose to see the message.

Practice: test a True or False function

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")
READ THE TESTS
  • Read the question.
  • Tap your answer.
What does assert not is_even(7) check?
Why test 0 and -2?
Someone changes == 0 to == 1. What happens when the tests run?
What does is_even(-2) return?
Write a test line that checks 9 is odd. assert not is_even(____)
What error does a failed assert raise?
StatementTrue 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.?
WHY THIS EXERCISEA useful test compares the result with a known right answer, so a wrong result is caught.

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.

← Wednesday