Testing
14 min
assert checks that a condition is True — if it isn't, Python raises
AssertionError and stops execution right there. It's the foundation
every testing framework (pytest, unittest) is built on top of.
def add(a, b):
return a + b
assert add(2, 3) == 5 # passes silently
assert add(2, 3) == 6, "math is broken" # raises AssertionError: math is broken
A test function is just a regular function, by convention named
test_..., whose whole job is to call the code under test and assert on
the result.
Arrange (nothing to set up here), Act (call square), Assert (check the result) — the same three-step shape works for tests of any complexity.
Sometimes the correct behavior IS raising an exception — you test that
with try/except, asserting the exception actually happened:
def test_raises_on_negative():
try:
square_root(-1)
assert False, "expected a ValueError" # only reached if it DIDN'T raise
except ValueError:
pass # correct — this is what we wanted
return True
Good tests aren't just "does it work for one normal input" — they cover edge cases (empty input, zero, negative numbers) and error conditions, not just the happy path.
Write `test_is_palindrome()`: assert that `is_palindrome('racecar')` is True, that `is_palindrome('hello')` is False, and that `is_palindrome('')` is True. Return True if every assertion passes.
Write `test_divide()`: assert `divide(10, 2) == 5.0`, and also assert that calling `divide(1, 0)` raises `ZeroDivisionError` (use try/except — catching it means the test passes; if it doesn't raise, the test should fail). Return True if both checks pass.
What's the point of the Arrange-Act-Assert pattern when writing a test?
You can write assert-based test functions, including tests that verify an exception is correctly raised.