File: test_amber_serializer_plugins.py

package info (click to toggle)
python-syrupy 5.1.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 4,460 kB
  • sloc: python: 6,156; makefile: 3
file content (187 lines) | stat: -rw-r--r-- 4,435 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
""" "Tests for the Amber serializer plugins for attrs, dataclasses, and Pydantic models."""

from dataclasses import dataclass

import attr
import pytest
from pydantic import BaseModel

from syrupy.extensions.amber import AmberSnapshotExtension
from syrupy.extensions.amber.attrs_plugin import AttrsPlugin
from syrupy.extensions.amber.dataclasses_plugin import DataclassPlugin
from syrupy.extensions.amber.pydantic_plugin import PydanticPlugin
from syrupy.extensions.amber.serializer import AmberDataSerializer


# region Data Classes
@attr.s
class AttrsPoint:
    x = attr.ib()
    y = attr.ib()


@dataclass
class DataclassPoint:
    x: int
    y: int


class PydanticPoint(BaseModel):
    x: int
    y: int


class Inner(BaseModel):
    val: int


class ComplexModel(BaseModel):
    """Complex Pydantic model for testing nested structures.

    Note: make sure field names are not sorted alphabetically to test ordering.
    """

    values: list[Inner]

    start: PydanticPoint
    end: PydanticPoint

    mapping: dict[str, Inner]


@dataclass
class Middle:
    inner: Inner
    other: str


@attr.s
class Outer:
    middle = attr.ib()
    tags = attr.ib(factory=list)


# endregion


# region Serializers
class AttrsSerializer(AmberDataSerializer):
    serializer_plugins = [AttrsPlugin]


class DataclassSerializer(AmberDataSerializer):
    serializer_plugins = [DataclassPlugin]


class PydanticSerializer(AmberDataSerializer):
    serializer_plugins = [PydanticPlugin]


class MixedSerializer(AmberDataSerializer):
    serializer_plugins = [AttrsPlugin, DataclassPlugin, PydanticPlugin]


# endregion


# region Extensions
class AmberAttrsExtension(AmberSnapshotExtension):
    serializer_class = AttrsSerializer


class AmberDataclassExtension(AmberSnapshotExtension):
    serializer_class = DataclassSerializer


class AmberPydanticExtension(AmberSnapshotExtension):
    serializer_class = PydanticSerializer


class AmberMixedExtension(AmberSnapshotExtension):
    serializer_class = MixedSerializer


# endregion


# region Fixtures


@pytest.fixture
def snapshot_attrs(snapshot) -> AmberSnapshotExtension:
    return snapshot.use_extension(AmberAttrsExtension)


@pytest.fixture
def snapshot_dataclass(snapshot) -> AmberSnapshotExtension:
    return snapshot.use_extension(AmberDataclassExtension)


@pytest.fixture
def snapshot_pydantic(snapshot) -> AmberSnapshotExtension:
    return snapshot.use_extension(AmberPydanticExtension)


@pytest.fixture
def snapshot_mixed(snapshot) -> AmberSnapshotExtension:
    return snapshot.use_extension(AmberMixedExtension)


# endregion


# region Tests
def test_attrs_plugin(snapshot_attrs):
    """Test serialization of an attrs class using the AmberAttrsExtension."""
    point = AttrsPoint(x=1, y=2)
    assert point == snapshot_attrs


def test_dataclasses_plugin(snapshot_dataclass):
    """Test serialization of a dataclass using the AmberDataclassExtension."""
    point = DataclassPoint(x=1, y=2)
    assert point == snapshot_dataclass


def test_pydantic_plugin(snapshot_pydantic):
    """Test serialization of a Pydantic model using the AmberPydanticExtension."""
    point = PydanticPoint(x=1, y=2)
    assert point == snapshot_pydantic


def test_mixed_plugins(snapshot_mixed):
    """Test serialization of mixed data types using the AmberMixedExtension."""
    complex_data = {
        "attrs": AttrsPoint(x=1, y=2),
        "dataclass": DataclassPoint(x=3, y=4),
        "pydantic": PydanticPoint(x=5, y=6),
        "list_mixed": [
            AttrsPoint(x=10, y=20),
            DataclassPoint(x=30, y=40),
        ],
    }
    assert complex_data == snapshot_mixed


def test_nested_structures(snapshot_mixed):
    """Test serialization of nested structures using the AmberMixedExtension."""
    data = Outer(middle=Middle(inner=Inner(val=42), other="nested"), tags=["c"])
    assert data == snapshot_mixed


def test_complex_pydantic_model(snapshot_pydantic):
    """Test serialization of a complex Pydantic model using the AmberPydanticExtension.

    Ensures nested models, lists, and dicts are handled correctly.
    Ensures field ordering is preserved as defined in the model.
    """
    data = ComplexModel(
        end=PydanticPoint(x=10, y=10),
        mapping={"first": Inner(val=100), "second": Inner(val=200)},
        start=PydanticPoint(x=0, y=0),
        values=[Inner(val=1), Inner(val=2)],
    )
    assert data == snapshot_pydantic


# endregion