pytest

Pytest

Python testing framework with fixtures, parametrize, and plugin ecosystem

Python
Testing
Default
Used by 1483 projects

Details

Language / Topic
pythonPython
Category
Testing

Rules

balanced
- Name test functions `test_<what>_<scenario>_<expected>` and place them in `tests/` mirroring `src/` structure.
- Use `pytest.fixture` for shared setup — prefer function-scope fixtures; use session scope only for expensive resources like DB connections.
- Parametrize test cases with `@pytest.mark.parametrize('input,expected', [(1, 2), (0, 0)])` instead of looping inside a test function.
- Raise `pytest.raises(ValueError, match='must be positive')` to assert specific exceptions with message matching.
- Mock external dependencies with `unittest.mock.patch` as a decorator or use `pytest-mock`'s `mocker` fixture.
- Name tests `test_<function>_<scenario>_<expected>`: `def test_calculate_tax_zero_income_returns_zero()` — pytest discovers any function prefixed with `test_`.
- Write fixtures with `@pytest.fixture`: `@pytest.fixture\ndef db_session():\n session = Session()\n yield session\n session.rollback()\n session.close()` — use `yield` for teardown logic.
- Use `@pytest.mark.parametrize('value,expected', [('hello', 5), ('', 0)])` to test multiple inputs with one test function — pytest generates a separate test case per tuple.
- Assert exceptions with `with pytest.raises(ValueError, match='must be positive'): validate_age(-1)` — the `match` parameter checks the exception message with a regex.
- Use `pytest-mock`'s `mocker.patch('module.Client')` in tests to replace external HTTP calls, email sending, and third-party APIs.
- Use `conftest.py` to share fixtures across a test module or the entire project — fixtures are scoped to the directory containing `conftest.py`.
- Mark slow tests with `@pytest.mark.slow` and run the fast suite with `pytest -m 'not slow'` in CI to keep feedback loops short.