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

1import importlib 1jklmnopqr

2from types import ModuleType 1jklmnopqr

3 

4import pytest 1jklmnopqr

5from dirty_equals import IsOneOf 1jklmnopqr

6from fastapi.testclient import TestClient 1jklmnopqr

7from sqlalchemy import Engine 1jklmnopqr

8 

9 

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

22 

23 

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

50 

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

102 

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

108 

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

117 

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 }