Code Project

Link Unit

Tuesday, February 11, 2025

PyTest Introduction

 Pytest is a popular Python testing framework known for its simplicity and powerful features. It provides functionalities to:

  • Write and execute unit tests, integration tests, or functional tests.
  • Support for test fixtures to manage setup and teardown.
  • Parametrize tests to run the same test with multiple inputs.
  • Filter, skip, or mark tests for better control.
  • Generate test reports with plugins (like pytest-html).
  • Compatible with other Python libraries and tools.

How Does Pytest Know Which Functions to Test?

Pytest automatically discovers test functions based on naming conventions. When you run pytest, it looks for files, classes, and functions that match specific patterns.

Rules for Test Discovery in Pytest

  1. File Names:
    Pytest looks for files with names starting with test_ or ending with _test.
    Example:

    • test_example.py
    • example_test.py
    • example.py ❌ (Not discovered unless explicitly specified)
  2. Function Names:
    Pytest looks for functions inside those files with names starting with test_.
    Example:

    def test_addition(): # ✅ Will be discovered
    assert 1 + 1 == 2 def addition_test(): # ❌ Won't be discovered assert 1 + 1 == 2
  3. Class Names:
    If you want to organize tests into classes, pytest looks for classes whose names start with Test. These classes should not have an __init__ method.
    Example:

    class TestMath: # ✅ Class will be discovered
    def test_addition(self): # ✅ Function will be discovered assert 1 + 1 == 2 class MathTests: # ❌ Class won't be discovered def test_subtraction(self): # ❌ Function won't be discovered assert 2 - 1 == 1
  4. Directories:
    Pytest scans directories recursively for test files. By default, it looks in:

    • The current working directory.
    • Any subdirectories that don’t start with . or _.

    Example directory structure:

    project/
    ├── tests/ │ ├── test_math.py │ ├── test_string.py └── app/ └── main.py

    Running pytest from the project/ directory will automatically find tests/test_math.py and tests/test_string.py.


Examples

Discovered Test

File: test_sample.py

def test_sum():
assert 2 + 2 == 4

Command:

$ pytest

Output:

========================================= test session starts =========================================
collected 1 item test_sample.py . [100%] ========================================== 1 passed in 0.01s ==========================================

Undiscovered Function

File: test_sample.py

def sum_test(): # Does not follow pytest naming convention
assert 2 + 2 == 4

Command:

$ pytest

Output:

========================================= test session starts =========================================
collected 0 items

How to Override the Default Discovery Rules?

  1. Run Specific Files/Functions Manually:
    You can explicitly specify the file or function to test:

    $ pytest test_example.py::test_specific_function
  2. Change Naming Patterns:
    Use the --pyargs or --collect-only options, or configure pytest.ini to adjust discovery:


    # pytest.ini [pytest] python_files = *_tests.py # Match files ending with '_tests.py' python_classes = *TestCase # Match classes ending with 'TestCase' python_functions = test_* # Match functions starting with 'test_'
  3. Run All Functions:
    Use the pytest --collect-only command to list all functions that match the discovery rules:

    $ pytest --collect-only

No comments: