Writing and Running Tests๏ƒ

๐Ÿงช This guide explains how to write and run tests using pytest, following the structure used in the template-project.

Writing good tests helps you avoid bugs, refactor safely, and ensure your code does what you expect โ€” even weeks or months later.


๐Ÿ“ Where Tests Go๏ƒ

All test code lives in the tests/ directory at the root of the project.

  • Each Python file in this folder starts with test_

  • Each test function inside starts with test_

  • You can organize tests by topic or module: test_utils.py, test_readers.py, etc.


โœ๏ธ Writing Your First Test๏ƒ

Tests are written as plain Python functions and typically use assertions to check behavior:

# tests/test_math.py

def test_addition():
    assert 1 + 1 == 2

To test your own project modules, just import them like normal:

# tests/test_tools.py
from template_project.tools import convert_units

def test_convert_units_basic():
    result = convert_units(10, "m", "km")
    assert result == 0.01

๐Ÿ’ก All test functions must start with test_ so pytest can discover them.


โ–ถ๏ธ Running Tests Locally๏ƒ

Make sure youโ€™ve installed the dev dependencies:

pip install -r requirements-dev.txt

Then run:

pytest

This will automatically find and run any test_*.py files under the tests/ folder.

To run a specific test file:

pytest tests/test_tools.py

To run a specific test function:

pytest tests/test_tools.py::test_convert_units_basic


๐Ÿ“Š Checking Test Coverage๏ƒ

Test coverage shows which lines of code are executed during testing. Higher coverage generally means better testing, but 100% coverage doesnโ€™t guarantee perfect tests.

Quick Coverage Check๏ƒ

# Basic coverage report in terminal
pytest --cov=template_project --cov-report=term-missing

This shows:

  • Percentage covered for each file

  • Missing lines that arenโ€™t tested

Detailed Coverage Analysis๏ƒ

For a comprehensive view, generate an HTML report:

pytest --cov=template_project --cov-report=html

Then open htmlcov/index.html in your browser.

Reading Coverage Reports๏ƒ

Terminal output example:

Name                    Stmts   Miss  Cover   Missing
-----------------------------------------------------
template_project/tools.py    20      3    85%   63, 96-97
template_project/utils.py    78     24    69%   79-80, 113-120
-----------------------------------------------------
TOTAL                       354     76    79%

What this means:

  • Stmts: Total executable statements

  • Miss: Statements not covered by tests

  • Cover: Percentage covered

  • Missing: Specific line numbers not tested

HTML report shows:

  • ๐ŸŸข Green lines: Covered by tests

  • ๐Ÿ”ด Red lines: Not covered by tests

  • ๐ŸŸก Yellow lines: Partially covered (e.g., branches)

Coverage Guidelines๏ƒ

Target coverage levels:

  • 80%+: Good coverage for most projects

  • 90%+: Excellent coverage

  • 100%: Often impractical (includes error handling, edge cases)

Focus on:

  • Core business logic functions

  • Complex algorithms and calculations

  • Error handling paths

  • Public API functions

Less critical to test:

  • Simple getters/setters

  • Third-party library integration

  • Configuration/setup code

If youโ€™re using pre-commit hooks, you can configure them to run pytest before each commit. This helps you catch test failures early.


Summary Cheatsheet๏ƒ

Task

Command

Run all tests

pytest

Run specific test file

pytest tests/test_xyz.py

Run specific test

pytest tests/test_xyz.py::test_name

Coverage report (terminal)

pytest --cov=template_project --cov-report=term-missing

Coverage report (HTML)

pytest --cov=template_project --cov-report=html

Install test tools

pip install -r requirements-dev.txt

โœ… Tests help you make confident changes. Use them early, and use them often!