# syrupy

> Pytest Snapshot Test Utility

- **URL**: https://www.freshcrate.ai/projects/syrupy
- **Author**: Noah Ulster
- **Category**: Frameworks
- **Latest version**: `v5.3.1` (2026-05-31)
- **License**: Unknown
- **Source**: https://github.com/syrupy-project/syrupy
- **Homepage**: https://pypi.org/project/syrupy/
- **Language**: Python
- **GitHub**: 837 stars, 50 forks
- **Registry**: pypi (`syrupy`)
- **Tags**: `pypi`

## Description

# syrupy

<img align="right" width="100px" height="100px" src="https://user-images.githubusercontent.com/2528959/69500147-85d71400-0ec6-11ea-867a-277881278e57.png" alt="Logo">

[![All Contributors](https://img.shields.io/github/all-contributors/syrupy-project/syrupy?color=ee8449&style=flat-square)](#contributors) [![Stage](https://img.shields.io/pypi/status/syrupy)](https://pypi.org/project/syrupy/) [![codecov](https://codecov.io/gh/syrupy-project/syrupy/graph/badge.svg?token=GB9EmYKPAl)](https://codecov.io/gh/syrupy-project/syrupy)

![Pytest>=8,<9.0.0](https://img.shields.io/badge/pytest-%3E=8,%20%3C9.0.0-green) [![Pypi](https://img.shields.io/pypi/v/syrupy)](https://pypi.org/project/syrupy/) [![Wheel](https://img.shields.io/pypi/wheel/syrupy)](https://pypi.org/project/syrupy/) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/syrupy) [![PyPI - Downloads](https://img.shields.io/pypi/dm/syrupy)](https://pypi.org/project/syrupy/) [![PyPI - License](https://img.shields.io/pypi/l/syrupy)](./LICENSE)

## Overview

Syrupy is a zero-dependency [pytest](https://docs.pytest.org/en/latest/) snapshot plugin. It enables developers to write tests which assert immutability of computed results.

## Motivation

Syrupy upholds three principles:

- Extensible: If a particular data type is not supported, users should be able to easily and quickly add support.
- Idiomatic: Snapshot testing should fit naturally among other test cases in pytest, e.g. `assert x == snapshot` vs. `snapshot.assert_match(x)`.
- Soundness: Snapshot tests should uncover even the most minute issues. Unlike other snapshot libraries, Syrupy will fail a test suite if a snapshot does not exist, not just on snapshot differences.

## Installation

```shell
python -m pip install syrupy
```

### Pytest and Python Compatibility

Syrupy will always be compatible with the latest version of Python and Pytest. If you're running an old version of Python or Pytest, you will need to use an older major version of Syrupy:

| Syrupy Version | Python Support | Pytest Support |
| -------------- | -------------- | -------------- |
| 5.x.x          | >=3.10         | >=8            |
| 4.x.x          | >=3.8.1,       | >=7,   <9      |
| 3.x.x          | >=3.7, <4      | >=5.1, <8      |
| 2.x.x          | >=3.6, <4      | >=5.1, <8      |

## Usage

### Basic Usage

In a pytest test file `test_file.py`:

```python
def test_foo(snapshot):
    actual = "Some computed value!"
    assert actual == snapshot
```

when you run `pytest`, the above test should fail due to a missing snapshot. Re-run pytest with the update snapshots flag like so:

```shell
pytest --snapshot-update
```

A snapshot file should be generated under a `__snapshots__` directory in the same directory as `test_file.py`. The `__snapshots__` directory and all its children should be committed along with your test code.

#### Usage in `unittest.TestCase` subclasses

[Due to limitations in `unittest` and `pytest`](https://docs.pytest.org/en/9.0.x/how-to/unittest.html#pytest-features-in-unittest-testcase-subclasses), the `snapshot` fixture is not directly usable in `TestCase` subclasses (including Django's `TestCase`).

Possible workarounds include using marks:

```python
from unittest import TestCase
import pytest

@pytest.fixture(scope="function")
def snapshot_in_class(request, snapshot):
    """
    Wraps snapshot fixture to provide instance snapshot property for
    unittest.TestCase tests
    """
    request.cls.snapshot = snapshot

class MyTest(TestCase):
    @pytest.mark.usefixtures("snapshot_in_class")
    def test_foo(self):
        actual = "Some computed value!"
        assert actual == self.snapshot
```

Or using a fixture with `autouse`:

```python
from unittest import TestCase
import pytest

class MyTest(TestCase):
    @pytest.fixture(autouse=True)
    def setupSnapshot(self, snapshot):
        self.snapshot = snapshot

    def test_foo(self):
        actual = "Some computed value!"
        assert actual == self.snapshot
```

#### Custom Objects

The default serializer supports all python built-in types and provides a sensible default for custom objects.

#### Representation

If you need to customise your object snapshot, it is as easy as overriding the default `__repr__` implementation.

```python
def __repr__(self) -> str:
    return "MyCustomClass(...)"
```

If you need bypass a custom object representation to use the amber standard, it is easy using the following helpers.

```python
def test_object_as_named_tuple(snapshot):
    assert snapshot == AmberDataSerializer.object_as_named_tuple(obj_with_custom_repr)
```

> See `test_snapshot_object_as_named_tuple_class` for an example on automatically doing this for all nested properties

#### Attributes

If you want to limit what properties are serialized at a class type level you could either:

**A**. Provide a filter function to the snapshot [exclude](#exclude) configuration option.

```py
def limit_foo_attrs(prop, path):
    allowed_foo_

## Recent releases

| Version | Date | Urgency | Changes |
| --- | --- | --- | --- |
| `v5.3.1` | 2026-05-31 | High | ## What's Changed  ### Fixes  * fix(test): mark pydantic and attrs as dependencies for running internal tests by @noahnu in https://github.com/syrupy-project/syrupy/pull/1108 -- **This only affects users trying to run the syrupy tests themselves, not consumers of syrupy.**  ### Misc  * chore(deps): update astral-sh/setup-uv action to v8.1.0 by @renovate[bot] in https://github.com/syrupy-project/syrupy/pull/1103 * chore(deps): update python docker tag to v3.14.4 by @renovate[bot] in http |
| `v5.2.0` | 2026-05-16 | High | ## What's Changed * chore(deps): update actions/checkout action to v6.0.2 by @renovate[bot] in https://github.com/syrupy-project/syrupy/pull/1065 * chore(deps): update actions/setup-python action to v6.2.0 by @renovate[bot] in https://github.com/syrupy-project/syrupy/pull/1066 * chore(deps): update dependency ruff to v0.14.14 by @renovate[bot] in https://github.com/syrupy-project/syrupy/pull/1067 * chore(deps): update dependency coverage to v7.13.2 by @renovate[bot] in https://github.com/syr |
| `5.1.0` | 2026-04-21 | Low | Imported from PyPI (5.1.0) |
| `v5.1.0` | 2026-01-25 | Low | # [5.1.0](https://github.com/syrupy-project/syrupy/compare/v5.0.0...v5.1.0) (2026-01-25)   ### Features  * add serializer plugin system; plugins for data models ([#1062](https://github.com/syrupy-project/syrupy/issues/1062)) ([df9bc8f](https://github.com/syrupy-project/syrupy/commit/df9bc8f6b3a222dde82167e10a2e6bb57456305a)) |
| `v5.1.0` | 2026-01-25 | Low | # [5.1.0](https://github.com/syrupy-project/syrupy/compare/v5.0.0...v5.1.0) (2026-01-25)   ### Features  * add serializer plugin system; plugins for data models ([#1062](https://github.com/syrupy-project/syrupy/issues/1062)) ([df9bc8f](https://github.com/syrupy-project/syrupy/commit/df9bc8f6b3a222dde82167e10a2e6bb57456305a)) |
| `v5.1.0` | 2026-01-25 | Low | # [5.1.0](https://github.com/syrupy-project/syrupy/compare/v5.0.0...v5.1.0) (2026-01-25)   ### Features  * add serializer plugin system; plugins for data models ([#1062](https://github.com/syrupy-project/syrupy/issues/1062)) ([df9bc8f](https://github.com/syrupy-project/syrupy/commit/df9bc8f6b3a222dde82167e10a2e6bb57456305a)) |
| `v5.1.0` | 2026-01-25 | Low | # [5.1.0](https://github.com/syrupy-project/syrupy/compare/v5.0.0...v5.1.0) (2026-01-25)   ### Features  * add serializer plugin system; plugins for data models ([#1062](https://github.com/syrupy-project/syrupy/issues/1062)) ([df9bc8f](https://github.com/syrupy-project/syrupy/commit/df9bc8f6b3a222dde82167e10a2e6bb57456305a)) |
| `v5.1.0` | 2026-01-25 | Low | # [5.1.0](https://github.com/syrupy-project/syrupy/compare/v5.0.0...v5.1.0) (2026-01-25)   ### Features  * add serializer plugin system; plugins for data models ([#1062](https://github.com/syrupy-project/syrupy/issues/1062)) ([df9bc8f](https://github.com/syrupy-project/syrupy/commit/df9bc8f6b3a222dde82167e10a2e6bb57456305a)) |
| `v5.1.0` | 2026-01-25 | Low | # [5.1.0](https://github.com/syrupy-project/syrupy/compare/v5.0.0...v5.1.0) (2026-01-25)   ### Features  * add serializer plugin system; plugins for data models ([#1062](https://github.com/syrupy-project/syrupy/issues/1062)) ([df9bc8f](https://github.com/syrupy-project/syrupy/commit/df9bc8f6b3a222dde82167e10a2e6bb57456305a)) |
| `v5.1.0` | 2026-01-25 | Low | # [5.1.0](https://github.com/syrupy-project/syrupy/compare/v5.0.0...v5.1.0) (2026-01-25)   ### Features  * add serializer plugin system; plugins for data models ([#1062](https://github.com/syrupy-project/syrupy/issues/1062)) ([df9bc8f](https://github.com/syrupy-project/syrupy/commit/df9bc8f6b3a222dde82167e10a2e6bb57456305a)) |

## Citation

- HTML: https://www.freshcrate.ai/projects/syrupy
- Markdown: https://www.freshcrate.ai/projects/syrupy.md
- Dependencies JSON: https://www.freshcrate.ai/api/projects/syrupy/deps

_Generated by freshcrate.ai. Indexes pypi releases for AI-agent ecosystem packages._
