test_*.py or *_test.py | Test file naming |
def test_function(): | Test function naming |
class TestClass: | Test class naming |
def test_method(self): | Test method in class |
assert x == y | Basic assertion |
assert x != y | Not equal |
assert x in collection | Membership |
assert x is None | Is None |
assert x is not None | Is not None |
assert isinstance(x, Type) | Type check |
assert 0.1 + 0.2 == pytest.approx(0.3) | Float comparison |
pytest | Run all tests |
pytest test_file.py | Run specific file |
pytest test_file.py::test_func | Run specific test |
pytest test_file.py::TestClass | Run test class |
pytest -k "keyword" | Run by keyword |
pytest -k "not slow" | Exclude by keyword |
pytest -m marker | Run by marker |
pytest -v | Verbose output |
pytest -vv | More verbose |
pytest -q | Quiet output |
pytest -s | Show print statements |
pytest --tb=short | Short traceback |
pytest --tb=long | Long traceback |
pytest --tb=no | No traceback |
pytest -l | Show locals in traceback |
pytest -x | Stop on first failure |
pytest --maxfail=3 | Stop after N failures |
pytest --lf | Rerun last failed |
pytest --ff | Failed first, then rest |
pytest -n auto | Parallel (pytest-xdist) |
pytest --durations=10 | Show 10 slowest tests |
@pytest.fixture | Define fixture |
def test_func(fixture_name): | Use fixture |
@pytest.fixture(scope="function") | Function scope (default) |
@pytest.fixture(scope="class") | Class scope |
@pytest.fixture(scope="module") | Module scope |
@pytest.fixture(scope="session") | Session scope |
@pytest.fixture(autouse=True) | Auto-use fixture |
yield value | Setup/teardown fixture |
@pytest.fixture(params=[1, 2, 3]) | Parametrized fixture |
request.param | Access fixture param |
conftest.py | Shared fixtures file |
@pytest.fixture(name="custom_name") | Custom fixture name |
tmp_path | Temporary directory (Path) |
tmp_path_factory | Temp dir factory |
capsys | Capture stdout/stderr |
capfd | Capture file descriptors |
monkeypatch | Modify objects |
request | Test request info |
@pytest.mark.skip | Skip test |
@pytest.mark.skip(reason="msg") | Skip with reason |
@pytest.mark.skipif(condition, reason="") | Conditional skip |
@pytest.mark.xfail | Expected failure |
@pytest.mark.xfail(raises=Exception) | Expected exception |
@pytest.mark.usefixtures("fix1", "fix2") | Use fixtures |
@pytest.mark.slow | Custom marker |
@pytest.mark.integration | Integration test marker |
pytest.ini: markers = slow: desc | Register marker |
pytest -m "slow" | Run marked tests |
pytest -m "not slow" | Exclude marked tests |
@pytest.mark.parametrize("arg", [1, 2, 3]) | Single parameter |
@pytest.mark.parametrize("a,b", [(1,2), (3,4)]) | Multiple parameters |
@pytest.mark.parametrize("a", [1, pytest.param(2, marks=pytest.mark.skip)]) | Param with marker |
@pytest.mark.parametrize("a", [1, 2], ids=["one", "two"]) | Custom IDs |
with pytest.raises(ValueError): | Expect exception |
with pytest.raises(ValueError, match="pattern"): | Match message |
exc_info = pytest.raises(ValueError)\nexc_info.value | Access exception |
@pytest.mark.xfail(raises=ValueError) | Expected to raise |
with pytest.warns(UserWarning): | Expect warning |
with pytest.warns(UserWarning, match="msg"): | Match warning |
pytest -W error::UserWarning | Treat warning as error |
@pytest.mark.filterwarnings("ignore::Warning") | Ignore warnings |
monkeypatch.setattr(obj, "attr", value) | Set attribute |
monkeypatch.setattr("module.func", mock_func) | Mock function |
monkeypatch.delattr(obj, "attr") | Delete attribute |
monkeypatch.setenv("VAR", "value") | Set env variable |
monkeypatch.delenv("VAR") | Delete env variable |
monkeypatch.chdir(path) | Change directory |
from unittest.mock import Mock, patch | Import mock |
mock = Mock(return_value=42) | Create mock |
mock.assert_called_once() | Assert called once |
@patch("module.function") | Patch decorator |
with patch("module.function") as mock: | Patch context manager |