Skip to content

Why test?

4 min read

In lesson 2.6 you typed ten scores into the Input box, one run at a time, and compared each answer with a table. That works once. By the end of this lesson, Python will run those checks for you every time you change the code, and you'll know what a passing check can and can't tell you.

Every lesson in this module runs in the browser, on a phone too. Only the last section of lesson 9.5 uses a computer.

A check you write once

Lesson 5.8 turned that table into a loop: eight scores, each with the letter it should get, and a line that printed only when an answer was wrong. That loop was a : code that runs your code on an input you chose and compares the result with the right answer.

Python has a statement for the comparing part. assert is followed by a condition: if it's true, nothing happens; if it's false, the program stops with an error. Each line is an . grades.py is lesson 5.8's grade_for in its own file, imported as in lesson 8.5:

from grades import grade_for

assert grade_for(90) == "A"
assert grade_for(85) == "A"
assert grade_for(49) == "F"
print("All checks passed")

In the editor, press Escape then Tab to move on.

Three true assertions print nothing, so the last line runs. In lesson 5.8 you broke grade_for on purpose, changing >= 85 to > 85. Here's that version. Predict what the assertions show:

What will this print?

Decide before you look. Guessing wrong is how this sticks.

from grades import grade_for

assert grade_for(90) == "A"
assert grade_for(85) == "A"
print("All checks passed")

Also in the folder with main.py:

grades.py

def grade_for(score):
    if score > 85:
        return "A"
    elif score >= 70:
        return "B"
    elif score >= 50:
        return "C"
    else:
        return "F"

Python prints

Traceback (most recent call last):
  File "main.py", line 4, in <module>
    assert grade_for(85) == "A"
           ^^^^^^^^^^^^^^^^^^^^
AssertionError

grade_for(85) returns 'B', so the assertion on line 4 is false and Python raises AssertionError. It names the line, but not the values: nothing says 'B' or 'A'.

Read the last line first (lesson 7.1): just AssertionError. If you expected something like got B, expected A, that's the most common guess, and plain assert doesn't give it. You learn which check failed, then you'd need a print to see what grade_for(85) returned. The next lesson's tool shows both values for you.

A bug that comes back

Change > 85 back to >= 85 and the assertion passes. Now keep it. Months later you tidy grades.py, type > again by accident, and the bug is back. That has a name: a .

A test you keep runs every time you run your tests, so the bug it checks can't come back quietly. Try it in the first runner: change >= 85 to > 85 in the grades.py tab and run. Line 4 stops it with AssertionError.

In lesson 7.4's six steps, a test is step 4, "check the guess", written down instead of done once. A failing test also does step 1, reproducing the bug on every run. And it does step 6 for you: the check stays in the file, so remembering is the computer's job.

One mistake makes a test that can never fail. You can add a message after a comma, assert condition, "message", and it's shown after AssertionError:. Brackets around both turn them into one tuple (lesson 4.3):

What a passing test tells you

Here's grade_for with a different bug. Every assertion passes:

from grades import grade_for

assert grade_for(90) == "A"
assert grade_for(85) == "A"
assert grade_for(75) == "B"
assert grade_for(49) == "F"
print("All checks passed")

In the editor, press Escape then Tab to move on.

A score of 70 gets a C, and no assertion tried 70. Add assert grade_for(70) == "B" above the print and run: now it fails.

Quick check

All the assertions for a function pass. What do you know?

Exercise

Test santim_to_birr

Here's santim_to_birr from lesson 5.1. Write at least three assertions above the print: a normal amount, 0 santim, and 100 santim, which should be exactly 1 birr. Then break the function (/ 10 instead of / 100) and check that an assertion stops it.

Your code

def santim_to_birr(santim):
    return santim / 100

# Your assertions here
print("All checks passed")

In the editor, press Escape then Tab to move on.

Show a solution

This is one way to solve it, not the only one. If yours prints the same thing, it works.

def santim_to_birr(santim):
    return santim / 100

assert santim_to_birr(2550) == 25.5
assert santim_to_birr(0) == 0
assert santim_to_birr(100) == 1
print("All checks passed")

Key takeaways

  • A test runs your code on an input you chose and compares the result with the answer it should give.
  • assert condition does nothing when it's true and raises AssertionError when it's false, without showing the values.
  • Keep your tests after a fix: if the bug comes back (a regression), they fail straight away.
  • A passing test shows the code is right for the inputs it tried, nothing more. Test the boundaries.