Lesson 9 · OKSTEM College · Associate of Science in Computer Science
Why Unit Testing?
Unit tests verify that individual functions and methods behave as specified. A passing test suite means: (a) the code meets its spec today, and (b) future changes that break existing behaviour are caught immediately.
The cost of a bug rises exponentially the later it is found. Unit tests catch bugs at the moment you write the code — far cheaper than finding them in production.
pytest Basics
Install once: pip install pytest. Write test files prefixed with test_; name test functions starting with test_. Run with pytest from the terminal.
# file: test_math_utils.pyfrom math_utils import clamp, is_prime
deftest_clamp_within_range():
assertclamp(50, 0, 100) == 50deftest_clamp_below_min():
assertclamp(-10, 0, 100) == 0deftest_clamp_above_max():
assertclamp(150, 0, 100) == 100deftest_is_prime_small_primes():
for n in [2, 3, 5, 7, 11]:
assertis_prime(n)
deftest_is_prime_composites():
for n in [4, 6, 9, 15]:
assertnotis_prime(n)
Fixtures & parametrize
Fixtures provide reusable setup/teardown. @pytest.mark.parametrize runs one test with many input/output pairs.
import pytest
@pytest.fixturedefsample_account():
from bank import BankAccount
returnBankAccount(1000) # fresh for every testdeftest_initial_balance(sample_account):
assert sample_account.balance == 1000deftest_negative_balance_raises(sample_account):
with pytest.raises(ValueError):
sample_account.balance = -1@pytest.mark.parametrize("n,expected", [
(2, True), (4, False), (17, True), (1, False)
])
deftest_is_prime_param(n, expected):
assertis_prime(n) == expected
Practice Problems
1. Write three test functions for a Stack class with push(), pop(), and is_empty().
def test_empty_stack():
s = Stack()
assert s.is_empty()
def test_push_pop():
s = Stack()
s.push(1); s.push(2)
assert s.pop() == 2 # LIFO
def test_pop_empty_raises():
s = Stack()
with pytest.raises(IndexError):
s.pop()
2. What does pytest.raises(ValueError) do?
It's a context manager that asserts the enclosed code raises ValueError.
If the exception is raised: test passes.
If it's NOT raised (or a different exception is raised): test fails.
Knowledge Check
pytest discovers test functions by looking for
pytest only searches files and functions matching its naming convention.