Coverage for tests/test_converter_serializer.py: 95%
152 statements
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-23 23:00 +0800
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-23 23:00 +0800
1"""測試數據類型轉換器和序列化器"""
3import pytest
4from dataclasses import dataclass
5from autocrud import ModelConverter, SerializerFactory, MemoryStorage, AutoCRUD
7# 嘗試導入可選依賴
8try:
9 from pydantic import BaseModel
10 HAS_PYDANTIC = True
11except ImportError:
12 HAS_PYDANTIC = False
14try:
15 from typing import TypedDict
16except ImportError:
17 from typing_extensions import TypedDict
20@dataclass
21class DataclassUser:
22 name: str
23 email: str
24 age: int
27if HAS_PYDANTIC:
28 class PydanticUser(BaseModel):
29 name: str
30 email: str
31 age: int
32else:
33 PydanticUser = None
36class TypedDictUser(TypedDict):
37 name: str
38 email: str
39 age: int
42class TestModelConverter:
43 """測試模型轉換器"""
45 def test_detect_dataclass_type(self):
46 """測試檢測 dataclass 類型"""
47 converter = ModelConverter()
48 model_type = converter.detect_model_type(DataclassUser)
49 assert model_type == "dataclass"
51 @pytest.mark.skipif(not HAS_PYDANTIC, reason="Pydantic not available")
52 def test_detect_pydantic_type(self):
53 """測試檢測 Pydantic 類型"""
54 converter = ModelConverter()
55 model_type = converter.detect_model_type(PydanticUser)
56 assert model_type == "pydantic"
58 def test_detect_typeddict_type(self):
59 """測試檢測 TypedDict 類型"""
60 converter = ModelConverter()
61 model_type = converter.detect_model_type(TypedDictUser)
62 assert model_type == "typeddict"
64 def test_extract_dataclass_fields(self):
65 """測試提取 dataclass 欄位"""
66 converter = ModelConverter()
67 fields = converter.extract_fields(DataclassUser)
69 assert 'name' in fields
70 assert 'email' in fields
71 assert 'age' in fields
72 assert fields['name'] == str
73 assert fields['age'] == int
75 @pytest.mark.skipif(not HAS_PYDANTIC, reason="Pydantic not available")
76 def test_extract_pydantic_fields(self):
77 """測試提取 Pydantic 欄位"""
78 converter = ModelConverter()
79 fields = converter.extract_fields(PydanticUser)
81 assert 'name' in fields
82 assert 'email' in fields
83 assert 'age' in fields
85 def test_dataclass_to_dict(self, sample_user_data):
86 """測試 dataclass 轉字典"""
87 converter = ModelConverter()
88 user = DataclassUser(**sample_user_data)
90 user_dict = converter.to_dict(user)
92 assert user_dict['name'] == sample_user_data['name']
93 assert user_dict['email'] == sample_user_data['email']
94 assert user_dict['age'] == sample_user_data['age']
96 def test_dict_to_dataclass(self, sample_user_data):
97 """測試字典轉 dataclass"""
98 converter = ModelConverter()
100 user = converter.from_dict(DataclassUser, sample_user_data)
102 assert isinstance(user, DataclassUser)
103 assert user.name == sample_user_data['name']
104 assert user.email == sample_user_data['email']
105 assert user.age == sample_user_data['age']
107 @pytest.mark.skipif(not HAS_PYDANTIC, reason="Pydantic not available")
108 def test_pydantic_conversion(self, sample_user_data):
109 """測試 Pydantic 模型轉換"""
110 converter = ModelConverter()
112 # 字典轉 Pydantic
113 user = converter.from_dict(PydanticUser, sample_user_data)
114 assert isinstance(user, PydanticUser)
115 assert user.name == sample_user_data['name']
117 # Pydantic 轉字典
118 user_dict = converter.to_dict(user)
119 assert user_dict['name'] == sample_user_data['name']
120 assert user_dict['email'] == sample_user_data['email']
122 def test_typeddict_conversion(self, sample_user_data):
123 """測試 TypedDict 轉換"""
124 converter = ModelConverter()
126 # 字典轉 TypedDict(實際上還是字典)
127 user = converter.from_dict(TypedDictUser, sample_user_data)
128 assert isinstance(user, dict)
129 assert user['name'] == sample_user_data['name']
131 # TypedDict 轉字典
132 user_dict = converter.to_dict(user)
133 assert user_dict == sample_user_data
136class TestSerializerFactory:
137 """測試序列化器工廠"""
139 def test_available_serializers(self):
140 """測試可用的序列化器"""
141 available = SerializerFactory.available_types()
143 assert 'json' in available
144 assert 'pickle' in available
145 assert 'msgpack' in available
147 def test_create_json_serializer(self):
148 """測試創建 JSON 序列化器"""
149 serializer = SerializerFactory.create('json')
151 test_data = {"name": "test", "value": 123}
152 serialized = serializer.serialize(test_data)
153 deserialized = serializer.deserialize(serialized)
155 assert isinstance(serialized, bytes)
156 assert deserialized == test_data
158 def test_create_pickle_serializer(self):
159 """測試創建 Pickle 序列化器"""
160 serializer = SerializerFactory.create('pickle')
162 test_data = {"name": "test", "value": 123, "list": [1, 2, 3]}
163 serialized = serializer.serialize(test_data)
164 deserialized = serializer.deserialize(serialized)
166 assert isinstance(serialized, bytes)
167 assert deserialized == test_data
169 def test_create_msgpack_serializer(self):
170 """測試創建 MsgPack 序列化器"""
171 try:
172 serializer = SerializerFactory.create('msgpack')
174 test_data = {"name": "test", "value": 123}
175 serialized = serializer.serialize(test_data)
176 deserialized = serializer.deserialize(serialized)
178 assert isinstance(serialized, bytes)
179 assert deserialized == test_data
180 except ImportError:
181 pytest.skip("msgpack not available")
183 def test_invalid_serializer_type(self):
184 """測試無效的序列化器類型"""
185 with pytest.raises(ValueError):
186 SerializerFactory.create('invalid_type')
189class TestIntegratedDataTypes:
190 """測試整合的數據類型支援"""
192 def test_dataclass_with_memory_storage(self, sample_user_data):
193 """測試 dataclass 與內存存儲的整合"""
194 storage = MemoryStorage()
195 crud = AutoCRUD(model=DataclassUser, storage=storage, resource_name="users")
197 created_user = crud.create(sample_user_data)
198 retrieved_user = crud.get(created_user['id'])
200 assert retrieved_user is not None
201 assert retrieved_user['name'] == sample_user_data['name']
203 @pytest.mark.skipif(not HAS_PYDANTIC, reason="Pydantic not available")
204 def test_pydantic_with_memory_storage(self, sample_user_data):
205 """測試 Pydantic 與內存存儲的整合"""
206 storage = MemoryStorage()
207 crud = AutoCRUD(model=PydanticUser, storage=storage, resource_name="users")
209 created_user = crud.create(sample_user_data)
210 retrieved_user = crud.get(created_user['id'])
212 assert retrieved_user is not None
213 assert retrieved_user['name'] == sample_user_data['name']
215 def test_typeddict_with_memory_storage(self, sample_user_data):
216 """測試 TypedDict 與內存存儲的整合"""
217 storage = MemoryStorage()
218 crud = AutoCRUD(model=TypedDictUser, storage=storage, resource_name="users")
220 created_user = crud.create(sample_user_data)
221 retrieved_user = crud.get(created_user['id'])
223 assert retrieved_user is not None
224 assert retrieved_user['name'] == sample_user_data['name']
226 def test_different_serializers_with_storage(self, sample_user_data):
227 """測試不同序列化器與存儲的組合"""
228 serializer_types = ['json', 'pickle']
230 for serializer_type in serializer_types:
231 serializer = SerializerFactory.create(serializer_type)
232 storage = MemoryStorage(serializer=serializer)
233 crud = AutoCRUD(model=DataclassUser, storage=storage, resource_name="users")
235 created_user = crud.create(sample_user_data)
236 retrieved_user = crud.get(created_user['id'])
238 assert retrieved_user is not None
239 assert retrieved_user['name'] == sample_user_data['name']