Writing and running your first tests

pytest · Essentials · 8 min

pytest is the standard Python test runner, and its zero-boilerplate style is why most projects actually write tests.

pytest finds and runs tests with almost no ceremony. Install it in your virtual environment (pip install pytest) and write a file whose name starts with test_ (or ends with _test.py). Inside, any function whose name starts with test is a test. You check results with the plain assert statement; no self.assertEqual needed.

Run pytest in the project root. It discovers test files recursively, imports them, runs every test function and prints a dot per pass, F per failure and E per error (an exception outside the assert, e.g. in setup). The summary line says how many passed and failed, and the exit code is non-zero on failure, so CI can rely on it.

Tests can also be methods on classes named Test... (without an __init__), which is just a way to group related tests; no base class is required.

Good first habits:

  • One behavior per test, named for that behavior: test_total_includes_tax.
  • Arrange, act, assert: set up inputs, call the code, check the outcome.
  • Tests must not depend on each other or on execution order.

Keep tests in a tests/ directory next to your package, and import the code under test like any user would. Use pytest -q for quiet output or -v to see each test name.

Example

# test_cart.py
def cart_total(prices, tax=0.2):
    return round(sum(prices) * (1 + tax), 2)

def test_empty_cart_is_zero():
    assert cart_total([]) == 0

def test_total_includes_tax():
    assert cart_total([10, 5]) == 18.0

class TestDiscounts:
    def test_zero_tax(self):
        assert cart_total([3, 4], tax=0) == 7

# $ pytest -q
# ...                                     [100%]
# 3 passed in 0.01s

Remember

  • Files test_*.py, functions test_*, classes Test*
  • Use plain assert for checks
  • Run pytest; non-zero exit code on failure
  • Tests must be independent of each other and of order

Watch out for

  • Naming a file tests.py or a function check_total, so pytest never collects it.

Check yourself

  1. Which function will pytest collect from test_math.py by default?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.pytest.org/en/stable/getting-started.html