Coverage for tests / test_tutorial / test_fastapi / test_simple_hero_api / test_tutorial001.py: 100%

41 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.simple_hero_api.{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 hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} 1abcdefghi

27 hero2_data = { 1abcdefghi

28 "name": "Spider-Boy", 

29 "secret_name": "Pedro Parqueador", 

30 "id": 9000, 

31 } 

32 response = client.post("/heroes/", json=hero1_data) 1abcdefghi

33 data = response.json() 1abcdefghi

34 

35 assert response.status_code == 200, response.text 1abcdefghi

36 assert data["name"] == hero1_data["name"] 1abcdefghi

37 assert data["secret_name"] == hero1_data["secret_name"] 1abcdefghi

38 assert data["id"] is not None 1abcdefghi

39 assert data["age"] is None 1abcdefghi

40 

41 response = client.post("/heroes/", json=hero2_data) 1abcdefghi

42 data = response.json() 1abcdefghi

43 

44 assert response.status_code == 200, response.text 1abcdefghi

45 assert data["name"] == hero2_data["name"] 1abcdefghi

46 assert data["secret_name"] == hero2_data["secret_name"] 1abcdefghi

47 assert data["id"] == hero2_data["id"], ( 1abcdefghi

48 "Up to this point it's still possible to " 

49 "set the ID of the hero in the request" 

50 ) 

51 assert data["age"] is None 1abcdefghi

52 

53 response = client.get("/heroes/") 1abcdefghi

54 data = response.json() 1abcdefghi

55 

56 assert response.status_code == 200, response.text 1abcdefghi

57 assert len(data) == 2 1abcdefghi

58 assert data[0]["name"] == hero1_data["name"] 1abcdefghi

59 assert data[0]["secret_name"] == hero1_data["secret_name"] 1abcdefghi

60 assert data[1]["name"] == hero2_data["name"] 1abcdefghi

61 assert data[1]["secret_name"] == hero2_data["secret_name"] 1abcdefghi

62 assert data[1]["id"] == hero2_data["id"] 1abcdefghi

63 

64 response = client.get("/openapi.json") 1abcdefghi

65 

66 assert response.status_code == 200, response.text 1abcdefghi

67 

68 assert response.json() == { 1abcdefghi

69 "openapi": "3.1.0", 

70 "info": {"title": "FastAPI", "version": "0.1.0"}, 

71 "paths": { 

72 "/heroes/": { 

73 "get": { 

74 "summary": "Read Heroes", 

75 "operationId": "read_heroes_heroes__get", 

76 "responses": { 

77 "200": { 

78 "description": "Successful Response", 

79 "content": {"application/json": {"schema": {}}}, 

80 } 

81 }, 

82 }, 

83 "post": { 

84 "summary": "Create Hero", 

85 "operationId": "create_hero_heroes__post", 

86 "requestBody": { 

87 "content": { 

88 "application/json": { 

89 "schema": {"$ref": "#/components/schemas/Hero"} 

90 } 

91 }, 

92 "required": True, 

93 }, 

94 "responses": { 

95 "200": { 

96 "description": "Successful Response", 

97 "content": {"application/json": {"schema": {}}}, 

98 }, 

99 "422": { 

100 "description": "Validation Error", 

101 "content": { 

102 "application/json": { 

103 "schema": { 

104 "$ref": "#/components/schemas/HTTPValidationError" 

105 } 

106 } 

107 }, 

108 }, 

109 }, 

110 }, 

111 } 

112 }, 

113 "components": { 

114 "schemas": { 

115 "HTTPValidationError": { 

116 "title": "HTTPValidationError", 

117 "type": "object", 

118 "properties": { 

119 "detail": { 

120 "title": "Detail", 

121 "type": "array", 

122 "items": { 

123 "$ref": "#/components/schemas/ValidationError" 

124 }, 

125 } 

126 }, 

127 }, 

128 "Hero": { 

129 "title": "Hero", 

130 "required": ["name", "secret_name"], 

131 "type": "object", 

132 "properties": { 

133 "id": { 

134 "title": "Id", 

135 "anyOf": [{"type": "integer"}, {"type": "null"}], 

136 }, 

137 "name": {"title": "Name", "type": "string"}, 

138 "secret_name": {"title": "Secret Name", "type": "string"}, 

139 "age": { 

140 "title": "Age", 

141 "anyOf": [{"type": "integer"}, {"type": "null"}], 

142 }, 

143 }, 

144 }, 

145 "ValidationError": { 

146 "title": "ValidationError", 

147 "required": ["loc", "msg", "type"], 

148 "type": "object", 

149 "properties": IsOneOf( 

150 { 

151 "loc": { 

152 "title": "Location", 

153 "type": "array", 

154 "items": { 

155 "anyOf": [ 

156 {"type": "string"}, 

157 {"type": "integer"}, 

158 ] 

159 }, 

160 }, 

161 "msg": {"title": "Message", "type": "string"}, 

162 "type": {"title": "Error Type", "type": "string"}, 

163 }, 

164 { 

165 "loc": { 

166 "title": "Location", 

167 "type": "array", 

168 "items": { 

169 "anyOf": [ 

170 {"type": "string"}, 

171 {"type": "integer"}, 

172 ] 

173 }, 

174 }, 

175 "msg": {"title": "Message", "type": "string"}, 

176 "type": {"title": "Error Type", "type": "string"}, 

177 "ctx": {"title": "Context", "type": "object"}, 

178 "input": {"title": "Input"}, 

179 }, 

180 ), 

181 }, 

182 } 

183 }, 

184 }