Coverage for tests/test_full_api.py: 100%
114 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"""測試完整 API 創建功能"""
3import pytest
4from dataclasses import dataclass
5from autocrud import AutoCRUD, MemoryStorage
8@dataclass
9class Book:
10 title: str
11 author: str
12 isbn: str
13 price: float
14 published_year: int
17class TestFullAPICreation:
18 """測試完整的 API 創建流程"""
20 @pytest.fixture
21 def sample_books(self):
22 """提供測試書籍數據"""
23 return [
24 {
25 "title": "Python 程式設計",
26 "author": "張三",
27 "isbn": "978-1111111111",
28 "price": 450.0,
29 "published_year": 2023,
30 },
31 {
32 "title": "Web 開發實戰",
33 "author": "李四",
34 "isbn": "978-2222222222",
35 "price": 520.0,
36 "published_year": 2024,
37 },
38 {
39 "title": "資料結構與算法",
40 "author": "王五",
41 "isbn": "978-3333333333",
42 "price": 380.0,
43 "published_year": 2022,
44 },
45 ]
47 def test_api_creation_basic(self):
48 """測試基本 API 創建"""
49 storage = MemoryStorage()
50 crud = AutoCRUD(model=Book, storage=storage, resource_name="books")
52 app = crud.create_fastapi_app(
53 title="書籍管理 API",
54 description="自動生成的書籍 CRUD API,支援完整的圖書管理功能",
55 version="1.0.0",
56 )
58 assert app.title == "書籍管理 API"
59 assert app.description == "自動生成的書籍 CRUD API,支援完整的圖書管理功能"
60 assert app.version == "1.0.0"
62 def test_api_routes_generation(self):
63 """測試 API 路由生成"""
64 storage = MemoryStorage()
65 crud = AutoCRUD(model=Book, storage=storage, resource_name="books")
67 app = crud.create_fastapi_app()
69 # 收集所有路由
70 routes = []
71 for route in app.routes:
72 if hasattr(route, "methods") and hasattr(route, "path"):
73 for method in route.methods:
74 if method not in ["HEAD", "OPTIONS"]:
75 routes.append(f"{method} {route.path}")
77 expected_routes = [
78 "POST /api/v1/books",
79 "GET /api/v1/books/{resource_id}",
80 "PUT /api/v1/books/{resource_id}",
81 "DELETE /api/v1/books/{resource_id}",
82 "GET /api/v1/books",
83 ]
85 for expected_route in expected_routes:
86 assert expected_route in routes
88 def test_api_with_preloaded_data(self, sample_books):
89 """測試預載數據的 API"""
90 storage = MemoryStorage()
91 crud = AutoCRUD(model=Book, storage=storage, resource_name="books")
93 # 預填測試數據
94 created_books = []
95 for book_data in sample_books:
96 book = crud.create(book_data)
97 created_books.append(book)
99 assert len(created_books) == 3
101 # 創建 API
102 app = crud.create_fastapi_app(
103 title="書籍管理 API",
104 description="預載數據的 API"
105 )
107 # 驗證數據仍然存在
108 all_books = crud.list_all()
109 assert len(all_books) == 3
111 # 驗證每本書的數據
112 for i, (book_id, book) in enumerate(all_books.items()):
113 original_book = sample_books[i]
114 assert book["title"] == original_book["title"]
115 assert book["author"] == original_book["author"]
116 assert book["isbn"] == original_book["isbn"]
118 def test_crud_operations_through_api_backend(self, sample_books):
119 """測試通過 API 後端進行 CRUD 操作"""
120 storage = MemoryStorage()
121 crud = AutoCRUD(model=Book, storage=storage, resource_name="books")
123 # 創建 API
124 app = crud.create_fastapi_app()
126 # 添加測試數據
127 created_books = []
128 for book_data in sample_books:
129 book = crud.create(book_data)
130 created_books.append(book)
132 # 測試列出所有書籍
133 all_books = crud.list_all()
134 assert len(all_books) == 3
136 # 測試獲取特定書籍
137 first_book_id = created_books[0]["id"]
138 retrieved_book = crud.get(first_book_id)
139 assert retrieved_book["title"] == sample_books[0]["title"]
141 # 測試更新書籍
142 updated_data = {
143 "title": "Python 高級程式設計",
144 "author": "張三",
145 "isbn": "978-1111111111",
146 "price": 550.0,
147 "published_year": 2024,
148 }
149 updated_book = crud.update(first_book_id, updated_data)
150 assert updated_book["title"] == "Python 高級程式設計"
151 assert updated_book["price"] == 550.0
153 # 測試刪除書籍
154 last_book_id = created_books[-1]["id"]
155 deleted = crud.delete(last_book_id)
156 assert deleted is True
158 # 驗證最終狀態
159 final_books = crud.list_all()
160 assert len(final_books) == 2 # 3 - 1 = 2
162 def test_api_with_different_models(self):
163 """測試不同模型的 API 創建"""
164 @dataclass
165 class Article:
166 title: str
167 content: str
168 author: str
169 published: bool
171 @dataclass
172 class User:
173 username: str
174 email: str
175 age: int
177 models = [
178 (Book, "books", "書籍管理 API"),
179 (Article, "articles", "文章管理 API"),
180 (User, "users", "用戶管理 API"),
181 ]
183 for model, resource_name, title in models:
184 storage = MemoryStorage()
185 crud = AutoCRUD(model=model, storage=storage, resource_name=resource_name)
187 app = crud.create_fastapi_app(title=title)
189 assert app.title == title
191 # 檢查路由
192 routes = []
193 for route in app.routes:
194 if hasattr(route, "path"):
195 routes.append(route.path)
197 assert f"/api/v1/{resource_name}" in routes
199 def test_api_health_and_docs_endpoints(self):
200 """測試 API 健康檢查和文檔端點"""
201 storage = MemoryStorage()
202 crud = AutoCRUD(model=Book, storage=storage, resource_name="books")
204 app = crud.create_fastapi_app()
206 # 收集所有路由路徑
207 paths = []
208 for route in app.routes:
209 if hasattr(route, "path"):
210 paths.append(route.path)
212 # 檢查標準端點
213 assert "/health" in paths
214 assert "/docs" in paths
215 assert "/redoc" in paths
216 assert "/openapi.json" in paths
218 def test_api_configuration_options(self):
219 """測試 API 配置選項"""
220 storage = MemoryStorage()
221 crud = AutoCRUD(model=Book, storage=storage, resource_name="books")
223 # 測試完整配置
224 app = crud.create_fastapi_app(
225 title="自定義標題",
226 description="自定義描述",
227 version="2.1.0",
228 prefix="/custom/v2"
229 )
231 assert app.title == "自定義標題"
232 assert app.description == "自定義描述"
233 assert app.version == "2.1.0"