Pytest snapshot testing utility that enables developers to write tests asserting immutability of computed results.
Overall
score
80%
Comprehensive pytest integration providing command-line options, session management, and reporting capabilities. Syrupy automatically registers as a pytest plugin and provides both CLI options and pytest fixtures for snapshot testing workflows.
Syrupy adds several command-line options to pytest for controlling snapshot behavior, reporting, and configuration.
def pytest_addoption(parser: "pytest.Parser") -> None:
"""
Register syrupy command-line options with pytest.
Adds options to pytest's argument parser for snapshot configuration,
update modes, reporting, and extension selection.
"""Essential options for snapshot update workflows and basic configuration.
# Update snapshots to match current test assertions
pytest --snapshot-update
# Show detailed information about snapshot operations
pytest --snapshot-details
# Warn about unused snapshots instead of failing tests
pytest --snapshot-warn-unused
# Disable colored output in test results
pytest --snapshot-no-colorsUsage examples:
# Standard workflow: run tests and update failing snapshots
pytest tests/
pytest --snapshot-update # Update snapshots after reviewing failures
# Generate detailed report with snapshot file locations
pytest --snapshot-details tests/
# CI/CD friendly: don't fail on unused snapshots, just warn
pytest --snapshot-warn-unused tests/
# Terminal-friendly: disable colors for log processing
pytest --snapshot-no-colors tests/ > test_results.logOptions for customizing snapshot behavior, extensions, and diff display.
# Use custom extension class by default
pytest --snapshot-default-extension=syrupy.extensions.json.JSONSnapshotExtension
# Control diff display mode for performance
pytest --snapshot-diff-mode=detailed # Show full diffs (default)
pytest --snapshot-diff-mode=disabled # Disable diffs for large snapshots
# Ignore specific file extensions during snapshot discovery
pytest --snapshot-ignore-file-extensions=.tmp,.cache
# Enable PyCharm diff integration
pytest --snapshot-patch-pycharm-diffUsage examples:
# Use JSON extension for all snapshots in a test run
pytest --snapshot-default-extension=syrupy.extensions.json.JSONSnapshotExtension tests/api/
# Optimize performance for tests with large snapshots
pytest --snapshot-diff-mode=disabled tests/integration/
# Ignore temporary and cache files when checking for unused snapshots
pytest --snapshot-ignore-file-extensions=.tmp,.cache,.bak tests/
# IDE integration for better diff viewing
pytest --snapshot-patch-pycharm-diff tests/Internal pytest hooks managing snapshot session lifecycle, test collection, and reporting.
def pytest_sessionstart(session: Any) -> None:
"""Initialize snapshot session before tests are collected and run."""
def pytest_collection_modifyitems(session: Any, config: Any, items: List["pytest.Item"]) -> None:
"""Process collected test items after collection."""
def pytest_collection_finish(session: Any) -> None:
"""Finalize test collection and select snapshot-related items."""
def pytest_runtest_logreport(report: pytest.TestReport) -> None:
"""Handle test run reports during setup, call, and teardown phases."""
def pytest_sessionfinish(session: "pytest.Session", exitstatus: int) -> None:
"""Finalize snapshot session and set appropriate exit status."""
def pytest_terminal_summary(terminalreporter: Any, exitstatus: int, config: Any) -> None:
"""Add syrupy-specific summary to pytest terminal output."""Primary pytest fixture providing the snapshot assertion interface to test functions.
@pytest.fixture
def snapshot(request: "pytest.FixtureRequest") -> "SnapshotAssertion":
"""
Pytest fixture providing snapshot assertion capability.
Parameters:
- request: Pytest fixture request containing configuration and test context
Returns:
SnapshotAssertion: Configured snapshot assertion instance
The fixture automatically configures based on CLI options:
- update_snapshots: From --snapshot-update flag
- extension_class: From --snapshot-default-extension option
- test_location: Derived from pytest test node
- session: Active snapshot session
"""Usage examples:
def test_basic_fixture(snapshot):
"""Standard fixture usage"""
result = {"message": "Hello world"}
assert result == snapshot
def test_fixture_configuration(snapshot):
"""Fixture respects CLI configuration"""
# If run with --snapshot-default-extension=syrupy.extensions.json.JSONSnapshotExtension
# this will automatically use JSON extension
data = {"users": [{"name": "Alice"}]}
assert data == snapshot
def test_multiple_snapshots(snapshot):
"""Fixture supports multiple snapshots per test"""
assert "first snapshot" == snapshot
assert {"second": "snapshot"} == snapshot
assert ["third", "snapshot"] == snapshot
# Session-scoped IDE integration fixture
@pytest.fixture(scope="session", autouse=True)
def _syrupy_apply_ide_patches(request: "pytest.FixtureRequest") -> Iterator[None]:
"""
Automatic fixture for IDE integration patches.
Applies when --snapshot-patch-pycharm-diff is enabled.
"""Custom assertion failure messages and diff display for snapshot comparisons.
def pytest_assertrepr_compare(config: "pytest.Config", op: str, left: Any, right: Any) -> Optional[List[str]]:
"""
Provide custom assertion representation for snapshot comparisons.
Parameters:
- config: Pytest configuration with syrupy options
- op: Comparison operator (typically "==")
- left: Left side of comparison (often SnapshotAssertion)
- right: Right side of comparison (test data)
Returns:
Optional[List[str]]: Custom assertion failure message lines
"""Example assertion output:
def test_failing_snapshot(snapshot):
actual = {"name": "Bob", "age": 25}
assert actual == snapshot
# When snapshot contains {"name": "Alice", "age": 30}, output shows:
#
# > assert actual == snapshot
# E AssertionError: assert {'age': 25, 'name': 'Bob'} == snapshot_name
# E [- snapshot_name] [+ received]
# E {
# E - 'age': 30,
# E + 'age': 25,
# E - 'name': 'Alice',
# E + 'name': 'Bob',
# E }Syrupy modifies pytest exit status based on snapshot-specific conditions.
EXIT_STATUS_FAIL_UNUSED = 1 # Exit code when unused snapshots foundExit status behavior:
# Normal test failures: exit code from pytest
pytest tests/ # Exit 1 if tests fail, 0 if pass
# Unused snapshots found: exit code 1 (unless --snapshot-warn-unused)
pytest tests/ # Exit 1 if unused snapshots exist
# With warning mode: exit code 0 even with unused snapshots
pytest --snapshot-warn-unused tests/ # Exit 0, just warns about unused
# Update mode: cleans up unused snapshots
pytest --snapshot-update tests/ # Removes unused snapshots, exit 0 if successfulEnvironment variables that affect syrupy behavior:
DISABLE_COLOR_ENV_VAR = "ANSI_COLORS_DISABLED" # Disable colored output
# Alternative: NO_COLOR environment variable also disables colorsUsage examples:
# Disable colors via environment variable
export ANSI_COLORS_DISABLED=1
pytest tests/
# Alternative color disabling
export NO_COLOR=1
pytest tests/
# Override in single command
ANSI_COLORS_DISABLED=1 pytest tests/Complete examples showing CLI integration in different scenarios:
# Development workflow
pytest tests/test_api.py # Run tests, see failures
pytest --snapshot-update tests/test_api.py # Update snapshots after review
# CI/CD pipeline
pytest --snapshot-warn-unused tests/ # Don't fail on unused snapshots
pytest --snapshot-no-colors tests/ > results.log # Log-friendly output
# Performance testing with large snapshots
pytest --snapshot-diff-mode=disabled tests/large_data/
# JSON API testing
pytest --snapshot-default-extension=syrupy.extensions.json.JSONSnapshotExtension tests/api/
# Comprehensive reporting
pytest --snapshot-details --snapshot-warn-unused tests/
# IDE integration
pytest --snapshot-patch-pycharm-diff tests/
# Custom extension with detailed reporting
pytest \
--snapshot-default-extension=myproject.extensions.CustomExtension \
--snapshot-details \
--snapshot-update \
tests/custom/Syrupy automatically registers as a pytest plugin through setuptools entry points:
# In pyproject.toml
[tool.poetry.plugins.pytest11]
syrupy = 'syrupy'This enables automatic discovery and loading when syrupy is installed, making all CLI options and fixtures available without additional configuration.
Install with Tessl CLI
npx tessl i tessl/pypi-syrupyevals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10