Introduction
A test is a small piece of code that checks another piece of code gives the right answer. Testing catches mistakes before your users (or your examiner) do, and it lets you change code with confidence.
Testing by hand is slow, and you can only test what you remember to try. Tests written as code run in a moment and repeat every check every time, so you can change a program without worrying about what you might have broken.
How it works
assert
def average(nums):
return sum(nums) / len(nums)
assert average([2, 4]) == 3
assert average([5]) == 5
print("All tests passed")assert condition does nothing when the condition is True, and stops the program with an AssertionError when it is False. Two checks pass here, so the last line prints.
A test that fails
def is_even(n):
return n % 2 == 1
assert is_even(4), "4 should be even"
print("not reached")is_even has a bug: it returns n % 2 == 1, which is the test for odd. The assert catches it at line 4, and the message after the comma, 4 should be even, explains what was expected. A failing test is good news: it found the bug for you.
Syntax
assert average([2, 4]) == 3
assert result == 5, "result should be 5"
assert abs(x - 0.3) < 1e-9
Example
def largest(nums):
best = nums[0]
for n in nums:
if n > best:
best = n
return best
tests = [([3, 9, 2], 9), ([-5, -2], -2), ([7], 7)]
for nums, expected in tests:
assert largest(nums) == expected, nums
print(len(tests), "tests passed")Good tests include the unusual inputs: negative numbers, a single item, the largest and smallest allowed values. Keeping the cases in a list makes it easy to add more. The practice problems on this site work the same way: hidden tests are mostly edge cases.
Line by line
largestis the function being tested.testsholds pairs of an input and the answer expected for it.- The loop unpacks each pair and calls the function.
assertstops the program if an answer is wrong, and shows the input.- If every check passes, the last line reports how many there were.
Expected result
3 tests passed
In the real world
Professional projects run thousands of tests each time the code changes, often automatically before anything is published. The tools have more features, such as Python's pytest, but the idea is exactly the same.
Common mistakes
- Testing only the example from the problem statement. Add edge cases.
- Comparing floats with
==:0.1 + 0.2 == 0.3is False. Useabs(a - b) < 1e-9. - Asserting the code against itself instead of against an answer you worked out by hand.
Best practices
- Add a test for each bug you fix, so that it cannot return.
- Test one idea at a time.
- Keep test cases in a list, so that adding one is easy.
Summary
A test checks code against an answer you worked out yourself. assert stops the program when a check fails. Good tests include edge cases, and floats need a tolerance.
Practice
Write three asserts for the factorial function from the recursion lesson, including the edge case factorial(0) == 1.
Quick check
Key takeaways
- A failing test is good news, because it found a bug.
- Test the smallest, largest and strangest inputs.
- Work out expected answers by hand.
Practice problems for this lesson
My notes
Write down what you want to remember from this lesson. Notes are saved on this device as you type, and appear on your dashboard.