Coverage for tests / test_tutorial / test_fastapi / test_relationships / test_tutorial001.py: 100%
87 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 1jklmnopqr
10@pytest.fixture( 1jklmnopqr
11 name="module",
12 params=[
13 pytest.param("tutorial001_py310"),
14 ],
15)
16def get_module(request: pytest.FixtureRequest, database_engine: Engine) -> ModuleType: 1jklmnopqr
17 mod = importlib.import_module( 1jklmnopqr
18 f"docs_src.tutorial.fastapi.relationships.{request.param}"
19 )
20 mod.engine = database_engine 1jklmnopqr
21 return mod 1jklmnopqr
24def test_tutorial(module: ModuleType): 1jklmnopqr
25 with TestClient(module.app) as client: 1abcdefghi
26 team_preventers = {"name": "Preventers", "headquarters": "Sharp Tower"} 1abcdefghi
27 team_z_force = {"name": "Z-Force", "headquarters": "Sister Margaret's Bar"} 1abcdefghi
28 response = client.post("/teams/", json=team_preventers) 1abcdefghi
29 assert response.status_code == 200, response.text 1abcdefghi
30 team_preventers_data = response.json() 1abcdefghi
31 team_preventers_id = team_preventers_data["id"] 1abcdefghi
32 response = client.post("/teams/", json=team_z_force) 1abcdefghi
33 assert response.status_code == 200, response.text 1abcdefghi
34 team_z_force_data = response.json() 1abcdefghi
35 team_z_force_id = team_z_force_data["id"] 1abcdefghi
36 response = client.get("/teams/") 1abcdefghi
37 data = response.json() 1abcdefghi
38 assert len(data) == 2 1abcdefghi
39 response = client.get("/teams/9000") 1abcdefghi
40 assert response.status_code == 404, response.text 1abcdefghi
41 response = client.patch( 1abcdefghi
42 f"/teams/{team_preventers_id}", json={"headquarters": "Preventers Tower"}
43 )
44 data = response.json() 1abcdefghi
45 assert response.status_code == 200, response.text 1abcdefghi
46 assert data["name"] == team_preventers["name"] 1abcdefghi
47 assert data["headquarters"] == "Preventers Tower" 1abcdefghi
48 response = client.patch("/teams/9000", json={"name": "Freedom League"}) 1abcdefghi
49 assert response.status_code == 404, response.text 1abcdefghi
51 hero1_data = { 1abcdefghi
52 "name": "Deadpond",
53 "secret_name": "Dive Wilson",
54 "team_id": team_z_force_id,
55 }
56 hero2_data = { 1abcdefghi
57 "name": "Spider-Boy",
58 "secret_name": "Pedro Parqueador",
59 "id": 9000,
60 }
61 hero3_data = { 1abcdefghi
62 "name": "Rusty-Man",
63 "secret_name": "Tommy Sharp",
64 "age": 48,
65 "team_id": team_preventers_id,
66 }
67 response = client.post("/heroes/", json=hero1_data) 1abcdefghi
68 assert response.status_code == 200, response.text 1abcdefghi
69 hero1 = response.json() 1abcdefghi
70 hero1_id = hero1["id"] 1abcdefghi
71 response = client.post("/heroes/", json=hero2_data) 1abcdefghi
72 assert response.status_code == 200, response.text 1abcdefghi
73 hero2 = response.json() 1abcdefghi
74 hero2_id = hero2["id"] 1abcdefghi
75 response = client.post("/heroes/", json=hero3_data) 1abcdefghi
76 assert response.status_code == 200, response.text 1abcdefghi
77 response = client.get("/heroes/9000") 1abcdefghi
78 assert response.status_code == 404, response.text 1abcdefghi
79 response = client.get("/heroes/") 1abcdefghi
80 assert response.status_code == 200, response.text 1abcdefghi
81 data = response.json() 1abcdefghi
82 assert len(data) == 3 1abcdefghi
83 response = client.get(f"/heroes/{hero1_id}") 1abcdefghi
84 assert response.status_code == 200, response.text 1abcdefghi
85 data = response.json() 1abcdefghi
86 assert data["name"] == hero1_data["name"] 1abcdefghi
87 assert data["team"]["name"] == team_z_force["name"] 1abcdefghi
88 response = client.patch( 1abcdefghi
89 f"/heroes/{hero2_id}", json={"secret_name": "Spider-Youngster"}
90 )
91 assert response.status_code == 200, response.text 1abcdefghi
92 response = client.patch("/heroes/9001", json={"name": "Dragon Cube X"}) 1abcdefghi
93 assert response.status_code == 404, response.text 1abcdefghi
94 response = client.delete(f"/heroes/{hero2_id}") 1abcdefghi
95 assert response.status_code == 200, response.text 1abcdefghi
96 response = client.get("/heroes/") 1abcdefghi
97 assert response.status_code == 200, response.text 1abcdefghi
98 data = response.json() 1abcdefghi
99 assert len(data) == 2 1abcdefghi
100 response = client.delete("/heroes/9000") 1abcdefghi
101 assert response.status_code == 404, response.text 1abcdefghi
103 response = client.get(f"/teams/{team_preventers_id}") 1abcdefghi
104 data = response.json() 1abcdefghi
105 assert response.status_code == 200, response.text 1abcdefghi
106 assert data["name"] == team_preventers_data["name"] 1abcdefghi
107 assert data["heroes"][0]["name"] == hero3_data["name"] 1abcdefghi
109 response = client.delete(f"/teams/{team_preventers_id}") 1abcdefghi
110 assert response.status_code == 200, response.text 1abcdefghi
111 response = client.delete("/teams/9000") 1abcdefghi
112 assert response.status_code == 404, response.text 1abcdefghi
113 response = client.get("/teams/") 1abcdefghi
114 assert response.status_code == 200, response.text 1abcdefghi
115 data = response.json() 1abcdefghi
116 assert len(data) == 1 1abcdefghi
118 response = client.get("/openapi.json") 1abcdefghi
119 assert response.status_code == 200, response.text 1abcdefghi
120 assert response.json() == { 1abcdefghi
121 "openapi": "3.1.0",
122 "info": {"title": "FastAPI", "version": "0.1.0"},
123 "paths": {
124 "/heroes/": {
125 "get": {
126 "summary": "Read Heroes",
127 "operationId": "read_heroes_heroes__get",
128 "parameters": [
129 {
130 "required": False,
131 "schema": {
132 "title": "Offset",
133 "type": "integer",
134 "default": 0,
135 },
136 "name": "offset",
137 "in": "query",
138 },
139 {
140 "required": False,
141 "schema": {
142 "title": "Limit",
143 "maximum": 100.0,
144 "type": "integer",
145 "default": 100,
146 },
147 "name": "limit",
148 "in": "query",
149 },
150 ],
151 "responses": {
152 "200": {
153 "description": "Successful Response",
154 "content": {
155 "application/json": {
156 "schema": {
157 "title": "Response Read Heroes Heroes Get",
158 "type": "array",
159 "items": {
160 "$ref": "#/components/schemas/HeroPublic"
161 },
162 }
163 }
164 },
165 },
166 "422": {
167 "description": "Validation Error",
168 "content": {
169 "application/json": {
170 "schema": {
171 "$ref": "#/components/schemas/HTTPValidationError"
172 }
173 }
174 },
175 },
176 },
177 },
178 "post": {
179 "summary": "Create Hero",
180 "operationId": "create_hero_heroes__post",
181 "requestBody": {
182 "content": {
183 "application/json": {
184 "schema": {
185 "$ref": "#/components/schemas/HeroCreate"
186 }
187 }
188 },
189 "required": True,
190 },
191 "responses": {
192 "200": {
193 "description": "Successful Response",
194 "content": {
195 "application/json": {
196 "schema": {
197 "$ref": "#/components/schemas/HeroPublic"
198 }
199 }
200 },
201 },
202 "422": {
203 "description": "Validation Error",
204 "content": {
205 "application/json": {
206 "schema": {
207 "$ref": "#/components/schemas/HTTPValidationError"
208 }
209 }
210 },
211 },
212 },
213 },
214 },
215 "/heroes/{hero_id}": {
216 "get": {
217 "summary": "Read Hero",
218 "operationId": "read_hero_heroes__hero_id__get",
219 "parameters": [
220 {
221 "required": True,
222 "schema": {"title": "Hero Id", "type": "integer"},
223 "name": "hero_id",
224 "in": "path",
225 }
226 ],
227 "responses": {
228 "200": {
229 "description": "Successful Response",
230 "content": {
231 "application/json": {
232 "schema": {
233 "$ref": "#/components/schemas/HeroPublicWithTeam"
234 }
235 }
236 },
237 },
238 "422": {
239 "description": "Validation Error",
240 "content": {
241 "application/json": {
242 "schema": {
243 "$ref": "#/components/schemas/HTTPValidationError"
244 }
245 }
246 },
247 },
248 },
249 },
250 "delete": {
251 "summary": "Delete Hero",
252 "operationId": "delete_hero_heroes__hero_id__delete",
253 "parameters": [
254 {
255 "required": True,
256 "schema": {"title": "Hero Id", "type": "integer"},
257 "name": "hero_id",
258 "in": "path",
259 }
260 ],
261 "responses": {
262 "200": {
263 "description": "Successful Response",
264 "content": {"application/json": {"schema": {}}},
265 },
266 "422": {
267 "description": "Validation Error",
268 "content": {
269 "application/json": {
270 "schema": {
271 "$ref": "#/components/schemas/HTTPValidationError"
272 }
273 }
274 },
275 },
276 },
277 },
278 "patch": {
279 "summary": "Update Hero",
280 "operationId": "update_hero_heroes__hero_id__patch",
281 "parameters": [
282 {
283 "required": True,
284 "schema": {"title": "Hero Id", "type": "integer"},
285 "name": "hero_id",
286 "in": "path",
287 }
288 ],
289 "requestBody": {
290 "content": {
291 "application/json": {
292 "schema": {
293 "$ref": "#/components/schemas/HeroUpdate"
294 }
295 }
296 },
297 "required": True,
298 },
299 "responses": {
300 "200": {
301 "description": "Successful Response",
302 "content": {
303 "application/json": {
304 "schema": {
305 "$ref": "#/components/schemas/HeroPublic"
306 }
307 }
308 },
309 },
310 "422": {
311 "description": "Validation Error",
312 "content": {
313 "application/json": {
314 "schema": {
315 "$ref": "#/components/schemas/HTTPValidationError"
316 }
317 }
318 },
319 },
320 },
321 },
322 },
323 "/teams/": {
324 "get": {
325 "summary": "Read Teams",
326 "operationId": "read_teams_teams__get",
327 "parameters": [
328 {
329 "required": False,
330 "schema": {
331 "title": "Offset",
332 "type": "integer",
333 "default": 0,
334 },
335 "name": "offset",
336 "in": "query",
337 },
338 {
339 "required": False,
340 "schema": {
341 "title": "Limit",
342 "maximum": 100.0,
343 "type": "integer",
344 "default": 100,
345 },
346 "name": "limit",
347 "in": "query",
348 },
349 ],
350 "responses": {
351 "200": {
352 "description": "Successful Response",
353 "content": {
354 "application/json": {
355 "schema": {
356 "title": "Response Read Teams Teams Get",
357 "type": "array",
358 "items": {
359 "$ref": "#/components/schemas/TeamPublic"
360 },
361 }
362 }
363 },
364 },
365 "422": {
366 "description": "Validation Error",
367 "content": {
368 "application/json": {
369 "schema": {
370 "$ref": "#/components/schemas/HTTPValidationError"
371 }
372 }
373 },
374 },
375 },
376 },
377 "post": {
378 "summary": "Create Team",
379 "operationId": "create_team_teams__post",
380 "requestBody": {
381 "content": {
382 "application/json": {
383 "schema": {
384 "$ref": "#/components/schemas/TeamCreate"
385 }
386 }
387 },
388 "required": True,
389 },
390 "responses": {
391 "200": {
392 "description": "Successful Response",
393 "content": {
394 "application/json": {
395 "schema": {
396 "$ref": "#/components/schemas/TeamPublic"
397 }
398 }
399 },
400 },
401 "422": {
402 "description": "Validation Error",
403 "content": {
404 "application/json": {
405 "schema": {
406 "$ref": "#/components/schemas/HTTPValidationError"
407 }
408 }
409 },
410 },
411 },
412 },
413 },
414 "/teams/{team_id}": {
415 "get": {
416 "summary": "Read Team",
417 "operationId": "read_team_teams__team_id__get",
418 "parameters": [
419 {
420 "required": True,
421 "schema": {"title": "Team Id", "type": "integer"},
422 "name": "team_id",
423 "in": "path",
424 }
425 ],
426 "responses": {
427 "200": {
428 "description": "Successful Response",
429 "content": {
430 "application/json": {
431 "schema": {
432 "$ref": "#/components/schemas/TeamPublicWithHeroes"
433 }
434 }
435 },
436 },
437 "422": {
438 "description": "Validation Error",
439 "content": {
440 "application/json": {
441 "schema": {
442 "$ref": "#/components/schemas/HTTPValidationError"
443 }
444 }
445 },
446 },
447 },
448 },
449 "delete": {
450 "summary": "Delete Team",
451 "operationId": "delete_team_teams__team_id__delete",
452 "parameters": [
453 {
454 "required": True,
455 "schema": {"title": "Team Id", "type": "integer"},
456 "name": "team_id",
457 "in": "path",
458 }
459 ],
460 "responses": {
461 "200": {
462 "description": "Successful Response",
463 "content": {"application/json": {"schema": {}}},
464 },
465 "422": {
466 "description": "Validation Error",
467 "content": {
468 "application/json": {
469 "schema": {
470 "$ref": "#/components/schemas/HTTPValidationError"
471 }
472 }
473 },
474 },
475 },
476 },
477 "patch": {
478 "summary": "Update Team",
479 "operationId": "update_team_teams__team_id__patch",
480 "parameters": [
481 {
482 "required": True,
483 "schema": {"title": "Team Id", "type": "integer"},
484 "name": "team_id",
485 "in": "path",
486 }
487 ],
488 "requestBody": {
489 "content": {
490 "application/json": {
491 "schema": {
492 "$ref": "#/components/schemas/TeamUpdate"
493 }
494 }
495 },
496 "required": True,
497 },
498 "responses": {
499 "200": {
500 "description": "Successful Response",
501 "content": {
502 "application/json": {
503 "schema": {
504 "$ref": "#/components/schemas/TeamPublic"
505 }
506 }
507 },
508 },
509 "422": {
510 "description": "Validation Error",
511 "content": {
512 "application/json": {
513 "schema": {
514 "$ref": "#/components/schemas/HTTPValidationError"
515 }
516 }
517 },
518 },
519 },
520 },
521 },
522 },
523 "components": {
524 "schemas": {
525 "HTTPValidationError": {
526 "title": "HTTPValidationError",
527 "type": "object",
528 "properties": {
529 "detail": {
530 "title": "Detail",
531 "type": "array",
532 "items": {
533 "$ref": "#/components/schemas/ValidationError"
534 },
535 }
536 },
537 },
538 "HeroCreate": {
539 "title": "HeroCreate",
540 "required": ["name", "secret_name"],
541 "type": "object",
542 "properties": {
543 "name": {"title": "Name", "type": "string"},
544 "secret_name": {"title": "Secret Name", "type": "string"},
545 "age": {
546 "title": "Age",
547 "anyOf": [{"type": "integer"}, {"type": "null"}],
548 },
549 "team_id": {
550 "title": "Team Id",
551 "anyOf": [{"type": "integer"}, {"type": "null"}],
552 },
553 },
554 },
555 "HeroPublic": {
556 "title": "HeroPublic",
557 "required": ["name", "secret_name", "id"],
558 "type": "object",
559 "properties": {
560 "name": {"title": "Name", "type": "string"},
561 "secret_name": {"title": "Secret Name", "type": "string"},
562 "age": {
563 "title": "Age",
564 "anyOf": [{"type": "integer"}, {"type": "null"}],
565 },
566 "team_id": {
567 "title": "Team Id",
568 "anyOf": [{"type": "integer"}, {"type": "null"}],
569 },
570 "id": {"title": "Id", "type": "integer"},
571 },
572 },
573 "HeroPublicWithTeam": {
574 "title": "HeroPublicWithTeam",
575 "required": ["name", "secret_name", "id"],
576 "type": "object",
577 "properties": {
578 "name": {"title": "Name", "type": "string"},
579 "secret_name": {"title": "Secret Name", "type": "string"},
580 "age": {
581 "title": "Age",
582 "anyOf": [{"type": "integer"}, {"type": "null"}],
583 },
584 "team_id": {
585 "title": "Team Id",
586 "anyOf": [{"type": "integer"}, {"type": "null"}],
587 },
588 "id": {"title": "Id", "type": "integer"},
589 "team": {
590 "anyOf": [
591 {"$ref": "#/components/schemas/TeamPublic"},
592 {"type": "null"},
593 ]
594 },
595 },
596 },
597 "HeroUpdate": {
598 "title": "HeroUpdate",
599 "type": "object",
600 "properties": {
601 "name": {
602 "title": "Name",
603 "anyOf": [{"type": "string"}, {"type": "null"}],
604 },
605 "secret_name": {
606 "title": "Secret Name",
607 "anyOf": [{"type": "string"}, {"type": "null"}],
608 },
609 "age": {
610 "title": "Age",
611 "anyOf": [{"type": "integer"}, {"type": "null"}],
612 },
613 "team_id": {
614 "title": "Team Id",
615 "anyOf": [{"type": "integer"}, {"type": "null"}],
616 },
617 },
618 },
619 "TeamCreate": {
620 "title": "TeamCreate",
621 "required": ["name", "headquarters"],
622 "type": "object",
623 "properties": {
624 "name": {"title": "Name", "type": "string"},
625 "headquarters": {"title": "Headquarters", "type": "string"},
626 },
627 },
628 "TeamPublic": {
629 "title": "TeamPublic",
630 "required": ["name", "headquarters", "id"],
631 "type": "object",
632 "properties": {
633 "name": {"title": "Name", "type": "string"},
634 "headquarters": {"title": "Headquarters", "type": "string"},
635 "id": {"title": "Id", "type": "integer"},
636 },
637 },
638 "TeamPublicWithHeroes": {
639 "title": "TeamPublicWithHeroes",
640 "required": ["name", "headquarters", "id"],
641 "type": "object",
642 "properties": {
643 "name": {"title": "Name", "type": "string"},
644 "headquarters": {"title": "Headquarters", "type": "string"},
645 "id": {"title": "Id", "type": "integer"},
646 "heroes": {
647 "title": "Heroes",
648 "type": "array",
649 "items": {"$ref": "#/components/schemas/HeroPublic"},
650 "default": [],
651 },
652 },
653 },
654 "TeamUpdate": {
655 "title": "TeamUpdate",
656 "type": "object",
657 "properties": {
658 "id": {
659 "title": "Id",
660 "anyOf": [{"type": "integer"}, {"type": "null"}],
661 },
662 "name": {
663 "title": "Name",
664 "anyOf": [{"type": "string"}, {"type": "null"}],
665 },
666 "headquarters": {
667 "title": "Headquarters",
668 "anyOf": [{"type": "string"}, {"type": "null"}],
669 },
670 },
671 },
672 "ValidationError": {
673 "title": "ValidationError",
674 "required": ["loc", "msg", "type"],
675 "type": "object",
676 "properties": IsOneOf(
677 {
678 "loc": {
679 "title": "Location",
680 "type": "array",
681 "items": {
682 "anyOf": [
683 {"type": "string"},
684 {"type": "integer"},
685 ]
686 },
687 },
688 "msg": {"title": "Message", "type": "string"},
689 "type": {"title": "Error Type", "type": "string"},
690 },
691 {
692 "loc": {
693 "title": "Location",
694 "type": "array",
695 "items": {
696 "anyOf": [
697 {"type": "string"},
698 {"type": "integer"},
699 ]
700 },
701 },
702 "msg": {"title": "Message", "type": "string"},
703 "type": {"title": "Error Type", "type": "string"},
704 "ctx": {"title": "Context", "type": "object"},
705 "input": {"title": "Input"},
706 },
707 ),
708 },
709 }
710 },
711 }