Coverage for tests / test_tutorial / test_fastapi / test_multiple_models / test_tutorial001.py: 100%
45 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-11-09 00:02 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2026-11-09 00:02 +0000
1import importlib 1jklmnopqr
2from types import ModuleType 1jklmnopqr
4import pytest 1jklmnopqr
5from dirty_equals import IsOneOf 1jklmnopqr
6from fastapi.testclient import TestClient 1jklmnopqr
7from sqlalchemy import Engine, inspect 1jklmnopqr
8from sqlalchemy.engine.reflection import Inspector 1jklmnopqr
11@pytest.fixture( 1jklmnopqr
12 name="module",
13 params=[
14 pytest.param("tutorial001_py310"),
15 ],
16)
17def get_module(request: pytest.FixtureRequest, database_engine: Engine) -> ModuleType: 1jklmnopqr
18 mod = importlib.import_module( 1jklmnopqr
19 f"docs_src.tutorial.fastapi.multiple_models.{request.param}"
20 )
21 mod.engine = database_engine 1jklmnopqr
22 return mod 1jklmnopqr
25def test_tutorial(module: ModuleType): 1jklmnopqr
26 with TestClient(module.app) as client: 1abcdefghi
27 hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} 1abcdefghi
28 hero2_data = { 1abcdefghi
29 "name": "Spider-Boy",
30 "secret_name": "Pedro Parqueador",
31 "id": 9000,
32 }
33 response = client.post("/heroes/", json=hero1_data) 1abcdefghi
34 data = response.json() 1abcdefghi
36 assert response.status_code == 200, response.text 1abcdefghi
37 assert data["name"] == hero1_data["name"] 1abcdefghi
38 assert data["secret_name"] == hero1_data["secret_name"] 1abcdefghi
39 assert data["id"] is not None 1abcdefghi
40 assert data["age"] is None 1abcdefghi
42 response = client.post("/heroes/", json=hero2_data) 1abcdefghi
43 data = response.json() 1abcdefghi
45 assert response.status_code == 200, response.text 1abcdefghi
46 assert data["name"] == hero2_data["name"] 1abcdefghi
47 assert data["secret_name"] == hero2_data["secret_name"] 1abcdefghi
48 assert data["id"] != hero2_data["id"], ( 1abcdefghi
49 "Now it's not possible to predefine the ID from the request, "
50 "it's now set by the database"
51 )
52 assert data["age"] is None 1abcdefghi
54 response = client.get("/heroes/") 1abcdefghi
55 data = response.json() 1abcdefghi
57 assert response.status_code == 200, response.text 1abcdefghi
58 assert len(data) == 2 1abcdefghi
59 assert data[0]["name"] == hero1_data["name"] 1abcdefghi
60 assert data[0]["secret_name"] == hero1_data["secret_name"] 1abcdefghi
61 assert data[1]["name"] == hero2_data["name"] 1abcdefghi
62 assert data[1]["secret_name"] == hero2_data["secret_name"] 1abcdefghi
63 assert data[1]["id"] != hero2_data["id"] 1abcdefghi
65 response = client.get("/openapi.json") 1abcdefghi
67 assert response.status_code == 200, response.text 1abcdefghi
69 assert response.json() == { 1abcdefghi
70 "openapi": "3.1.0",
71 "info": {"title": "FastAPI", "version": "0.1.0"},
72 "paths": {
73 "/heroes/": {
74 "get": {
75 "summary": "Read Heroes",
76 "operationId": "read_heroes_heroes__get",
77 "responses": {
78 "200": {
79 "description": "Successful Response",
80 "content": {
81 "application/json": {
82 "schema": {
83 "title": "Response Read Heroes Heroes Get",
84 "type": "array",
85 "items": {
86 "$ref": "#/components/schemas/HeroPublic"
87 },
88 }
89 }
90 },
91 }
92 },
93 },
94 "post": {
95 "summary": "Create Hero",
96 "operationId": "create_hero_heroes__post",
97 "requestBody": {
98 "content": {
99 "application/json": {
100 "schema": {
101 "$ref": "#/components/schemas/HeroCreate"
102 }
103 }
104 },
105 "required": True,
106 },
107 "responses": {
108 "200": {
109 "description": "Successful Response",
110 "content": {
111 "application/json": {
112 "schema": {
113 "$ref": "#/components/schemas/HeroPublic"
114 }
115 }
116 },
117 },
118 "422": {
119 "description": "Validation Error",
120 "content": {
121 "application/json": {
122 "schema": {
123 "$ref": "#/components/schemas/HTTPValidationError"
124 }
125 }
126 },
127 },
128 },
129 },
130 }
131 },
132 "components": {
133 "schemas": {
134 "HTTPValidationError": {
135 "title": "HTTPValidationError",
136 "type": "object",
137 "properties": {
138 "detail": {
139 "title": "Detail",
140 "type": "array",
141 "items": {
142 "$ref": "#/components/schemas/ValidationError"
143 },
144 }
145 },
146 },
147 "HeroCreate": {
148 "title": "HeroCreate",
149 "required": ["name", "secret_name"],
150 "type": "object",
151 "properties": {
152 "name": {"title": "Name", "type": "string"},
153 "secret_name": {"title": "Secret Name", "type": "string"},
154 "age": {
155 "title": "Age",
156 "anyOf": [{"type": "integer"}, {"type": "null"}],
157 },
158 },
159 },
160 "HeroPublic": {
161 "title": "HeroPublic",
162 "required": ["id", "name", "secret_name"],
163 "type": "object",
164 "properties": {
165 "id": {"title": "Id", "type": "integer"},
166 "name": {"title": "Name", "type": "string"},
167 "secret_name": {"title": "Secret Name", "type": "string"},
168 "age": {
169 "title": "Age",
170 "anyOf": [{"type": "integer"}, {"type": "null"}],
171 },
172 },
173 },
174 "ValidationError": {
175 "title": "ValidationError",
176 "required": ["loc", "msg", "type"],
177 "type": "object",
178 "properties": IsOneOf(
179 {
180 "loc": {
181 "title": "Location",
182 "type": "array",
183 "items": {
184 "anyOf": [
185 {"type": "string"},
186 {"type": "integer"},
187 ]
188 },
189 },
190 "msg": {"title": "Message", "type": "string"},
191 "type": {"title": "Error Type", "type": "string"},
192 },
193 {
194 "loc": {
195 "title": "Location",
196 "type": "array",
197 "items": {
198 "anyOf": [
199 {"type": "string"},
200 {"type": "integer"},
201 ]
202 },
203 },
204 "msg": {"title": "Message", "type": "string"},
205 "type": {"title": "Error Type", "type": "string"},
206 "ctx": {"title": "Context", "type": "object"},
207 "input": {"title": "Input"},
208 },
209 ),
210 },
211 }
212 },
213 }
215 # Test inherited indexes
216 insp: Inspector = inspect(module.engine) 1abcdefghi
217 indexes = insp.get_indexes(str(module.Hero.__tablename__)) 1abcdefghi
218 assert { 1abcdefghi
219 index["name"]: (index["column_names"], index["unique"]) for index in indexes
220 } == {
221 "ix_hero_name": (["name"], False),
222 "ix_hero_age": (["age"], False),
223 }