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
- Use Fixtures: Reuse setup/teardown code.
- Categorize Tests: Use markers for organization.
- Keep Tests Isolated: Ensure tests do not depend on each other.
- Fail Fast: Use
--maxfail=1
during debugging. - 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!