Skip to content

Getting Started

Installation

Install pytest-ditto from PyPI:

pip install pytest-ditto

For optional recorder plugins:

pip install pytest-ditto[pandas]    # pandas DataFrame recorders
pip install pytest-ditto[polars]    # polars DataFrame recorders
pip install pytest-ditto[pyarrow]   # PyArrow Table recorders

Your First Snapshot Test

Create a test file test_example.py:

import ditto


def fn(x: int) -> int:
    return x + 1


def test_fn(snapshot) -> None:
    x = 1
    result = fn(x)
    assert result == snapshot(result, key="fn")

Run it:

pytest test_example.py

First run: The snapshot fixture records result to a .ditto/ directory next to your test file. The test passes.

Subsequent runs: The stored value is loaded and compared. If fn changes its behaviour, the assertion fails.

Updating Snapshots

When you intentionally change behaviour, regenerate snapshots:

ditto update

Or target specific tests:

ditto update tests/ -k test_fn

Choosing a Recorder

By default, snapshots are persisted as deterministic strict JSON. No mark is needed; @ditto.json is available when being explicit is clearer. Use a mark to select a different installed format:

import ditto


@ditto.yaml
def test_with_yaml(snapshot):
    data = {"name": "pytest-ditto", "version": 1}
    assert data == snapshot(data, key="meta")


@ditto.json
def test_with_json(snapshot):
    data = {"name": "pytest-ditto", "version": 1}
    assert data == snapshot(data, key="meta")

The built-in recorders are:

Mark Format File Extension
no mark / @ditto.json strict JSON (default) .json
@ditto.yaml YAML .yaml

Strict JSON accepts exact built-in None, bool, int, finite float, str, list, and dict values recursively; dictionary keys must be exact built-in strings. Choose an installed external recorder for other values.

What's Next?