Skip to main content

Pytest Cheat Sheet

·600 words·3 mins
Ankur Rathore
Author
Ankur Rathore
Senior Systems Engineer pivoting to High-Performance Infrastructure. Building zero-allocation network drivers and cache-friendly data structures.

Pytest Cheat Sheet
#

Pytest is a powerful and easy-to-use testing framework for Python. This cheat sheet covers its essential features, commands, and best practices to streamline your testing workflow.


Getting Started
#

Installation
#

Install pytest using pip:

pip install pytest

Basic Test File
#

Save the following as test_sample.py:

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

Run tests:

pytest

Writing Tests
#

Test Naming Convention
#

  • Test files should start with test_ or end with _test.
  • Test functions should start with test_.

Assertions
#

Use Python’s assert statement for validations:

def test_math():
    assert 2 * 2 == 4
    assert "abc" in "abcdef"

Markers
#

Markers allow you to categorize tests:

import pytest

@pytest.mark.slow
def test_slow_operation():
    import time
    time.sleep(5)
    assert True

Run marked tests:

pytest -m slow

Fixtures
#

Basic Fixture
#

Fixtures set up resources needed for your tests:

import pytest

@pytest.fixture
def sample_data():
    return [1, 2, 3]

def test_data_length(sample_data):
    assert len(sample_data) == 3

Fixture Scope
#

Control how often a fixture is run:

  • function (default)
  • class
  • module
  • session
@pytest.fixture(scope="module")
def db_connection():
    return create_database_connection()

Running Tests
#

Run All Tests
#

pytest

Run Specific File
#

pytest test_file.py

Run Specific Test
#

pytest test_file.py::test_function

Verbose Output
#

pytest -v

Test Discovery
#

Check Collected Tests
#

pytest --collect-only

Ignore Files/Directories
#

Add a pytest.ini file:

[pytest]
addopts = --maxfail=3 --disable-warnings
norecursedirs = .git venv

Parameterized Tests
#

Test multiple input values using @pytest.mark.parametrize:

@pytest.mark.parametrize("input,expected", [
    (1, 2),
    (2, 4),
    (3, 6)
])
def test_double(input, expected):
    assert input * 2 == expected

Debugging
#

Drop Into Debugger on Failure
#

pytest --pdb

Print Statements #

Use -s to show print statements:

pytest -s

Plugins
#

Extend pytest with plugins:

pip install pytest-cov  # For coverage reporting

Example usage:

pytest --cov=my_module

Useful Plugins
#

  • pytest-mock: Mocking library integration.
  • pytest-django: Django testing support.
  • pytest-xdist: Run tests in parallel.

Skipping and Expected Failures
#

Skip a Test
#

@pytest.mark.skip(reason="Not implemented")
def test_placeholder():
    assert False

Conditionally Skip
#

@pytest.mark.skipif(sys.version_info < (3, 8), reason="Requires Python 3.8")
def test_new_feature():
    assert True

Expected Failures
#

@pytest.mark.xfail(reason="Known bug")
def test_known_issue():
    assert False

Test Coverage
#

Install Coverage Plugin
#

pip install pytest-cov

Run Tests with Coverage
#

pytest --cov=my_module

Generate HTML Report
#

pytest --cov=my_module --cov-report=html

Using pytest-mock
#

Mocking with pytest-mock
#

Use pytest-mock to simplify mocking in your tests:

pip install pytest-mock

Example:

def test_mock_function(mocker):
    mock_function = mocker.patch("module_name.function_name")
    mock_function.return_value = "mocked_value"

    result = module_name.function_name()
    assert result == "mocked_value"

Checking Exception Handling
#

You can use pytest.raises to ensure exceptions are properly handled:

def test_exception_handling():
    with pytest.raises(ValueError, match="Invalid input"):
        function_that_raises_value_error()

Using conftest.py
#

The conftest.py file is a special file used to share fixtures and hooks across multiple test files in a pytest project. Place it in the root directory or any subdirectory of your tests.

Example: Shared Fixture
#

Create conftest.py:

import pytest

@pytest.fixture
def shared_fixture():
    return "shared resource"

Use the fixture in your test files without importing:

def test_shared_fixture(shared_fixture):
    assert shared_fixture == "shared resource"

Advanced Usage
#

  • Hooks: Customize pytest behavior, such as modifying command-line options or test discovery.
  • Scoped Fixtures: Centralize setup and teardown logic.

Example of a hook in conftest.py:

def pytest_addoption(parser):
    parser.addoption("--custom-flag", action="store", default="default_value")

@pytest.fixture
def custom_flag(request):
    return request.config.getoption("--custom-flag")

Run with:

pytest --custom-flag=some_value

Best Practices
#

  1. Use Fixtures: Reuse setup/teardown code.
  2. Categorize Tests: Use markers for organization.
  3. Keep Tests Isolated: Ensure tests do not depend on each other.
  4. Fail Fast: Use --maxfail=1 during debugging.
  5. Write Descriptive Names: Use meaningful test and function names.

With this cheat sheet, you can start using pytest effectively for your testing needs, including advanced use cases like mocking, shared fixtures, and exception handling. Happy testing!