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

49 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(f"docs_src.tutorial.fastapi.update.{request.param}") 1jklmnopqr

18 mod.engine = database_engine 1jklmnopqr

19 return mod 1jklmnopqr

20 

21 

22def test_tutorial(module: ModuleType): 1jklmnopqr

23 with TestClient(module.app) as client: 1abcdefghi

24 hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} 1abcdefghi

25 hero2_data = { 1abcdefghi

26 "name": "Spider-Boy", 

27 "secret_name": "Pedro Parqueador", 

28 "id": 9000, 

29 } 

30 hero3_data = { 1abcdefghi

31 "name": "Rusty-Man", 

32 "secret_name": "Tommy Sharp", 

33 "age": 48, 

34 } 

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

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

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

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

39 hero2 = response.json() 1abcdefghi

40 hero2_id = hero2["id"] 1abcdefghi

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

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

43 hero3 = response.json() 1abcdefghi

44 hero3_id = hero3["id"] 1abcdefghi

45 response = client.get(f"/heroes/{hero2_id}") 1abcdefghi

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

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

48 assert response.status_code == 404, response.text 1abcdefghi

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

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

51 data = response.json() 1abcdefghi

52 assert len(data) == 3 1abcdefghi

53 

54 response = client.patch( 1abcdefghi

55 f"/heroes/{hero2_id}", json={"secret_name": "Spider-Youngster"} 

56 ) 

57 data = response.json() 1abcdefghi

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

59 assert data["name"] == hero2_data["name"], "The name should not be set to none" 1abcdefghi

60 assert data["secret_name"] == "Spider-Youngster", ( 1abcdefghi

61 "The secret name should be updated" 

62 ) 

63 

64 response = client.patch(f"/heroes/{hero3_id}", json={"age": None}) 1abcdefghi

65 data = response.json() 1abcdefghi

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

67 assert data["name"] == hero3_data["name"] 1abcdefghi

68 assert data["age"] is None, ( 1abcdefghi

69 "A field should be updatable to None, even if that's the default" 

70 ) 

71 

72 response = client.patch("/heroes/9001", json={"name": "Dragon Cube X"}) 1abcdefghi

73 assert response.status_code == 404, response.text 1abcdefghi

74 

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

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

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

78 "openapi": "3.1.0", 

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

80 "paths": { 

81 "/heroes/": { 

82 "get": { 

83 "summary": "Read Heroes", 

84 "operationId": "read_heroes_heroes__get", 

85 "parameters": [ 

86 { 

87 "required": False, 

88 "schema": { 

89 "title": "Offset", 

90 "type": "integer", 

91 "default": 0, 

92 }, 

93 "name": "offset", 

94 "in": "query", 

95 }, 

96 { 

97 "required": False, 

98 "schema": { 

99 "title": "Limit", 

100 "maximum": 100.0, 

101 "type": "integer", 

102 "default": 100, 

103 }, 

104 "name": "limit", 

105 "in": "query", 

106 }, 

107 ], 

108 "responses": { 

109 "200": { 

110 "description": "Successful Response", 

111 "content": { 

112 "application/json": { 

113 "schema": { 

114 "title": "Response Read Heroes Heroes Get", 

115 "type": "array", 

116 "items": { 

117 "$ref": "#/components/schemas/HeroPublic" 

118 }, 

119 } 

120 } 

121 }, 

122 }, 

123 "422": { 

124 "description": "Validation Error", 

125 "content": { 

126 "application/json": { 

127 "schema": { 

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

129 } 

130 } 

131 }, 

132 }, 

133 }, 

134 }, 

135 "post": { 

136 "summary": "Create Hero", 

137 "operationId": "create_hero_heroes__post", 

138 "requestBody": { 

139 "content": { 

140 "application/json": { 

141 "schema": { 

142 "$ref": "#/components/schemas/HeroCreate" 

143 } 

144 } 

145 }, 

146 "required": True, 

147 }, 

148 "responses": { 

149 "200": { 

150 "description": "Successful Response", 

151 "content": { 

152 "application/json": { 

153 "schema": { 

154 "$ref": "#/components/schemas/HeroPublic" 

155 } 

156 } 

157 }, 

158 }, 

159 "422": { 

160 "description": "Validation Error", 

161 "content": { 

162 "application/json": { 

163 "schema": { 

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

165 } 

166 } 

167 }, 

168 }, 

169 }, 

170 }, 

171 }, 

172 "/heroes/{hero_id}": { 

173 "get": { 

174 "summary": "Read Hero", 

175 "operationId": "read_hero_heroes__hero_id__get", 

176 "parameters": [ 

177 { 

178 "required": True, 

179 "schema": {"title": "Hero Id", "type": "integer"}, 

180 "name": "hero_id", 

181 "in": "path", 

182 } 

183 ], 

184 "responses": { 

185 "200": { 

186 "description": "Successful Response", 

187 "content": { 

188 "application/json": { 

189 "schema": { 

190 "$ref": "#/components/schemas/HeroPublic" 

191 } 

192 } 

193 }, 

194 }, 

195 "422": { 

196 "description": "Validation Error", 

197 "content": { 

198 "application/json": { 

199 "schema": { 

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

201 } 

202 } 

203 }, 

204 }, 

205 }, 

206 }, 

207 "patch": { 

208 "summary": "Update Hero", 

209 "operationId": "update_hero_heroes__hero_id__patch", 

210 "parameters": [ 

211 { 

212 "required": True, 

213 "schema": {"title": "Hero Id", "type": "integer"}, 

214 "name": "hero_id", 

215 "in": "path", 

216 } 

217 ], 

218 "requestBody": { 

219 "content": { 

220 "application/json": { 

221 "schema": { 

222 "$ref": "#/components/schemas/HeroUpdate" 

223 } 

224 } 

225 }, 

226 "required": True, 

227 }, 

228 "responses": { 

229 "200": { 

230 "description": "Successful Response", 

231 "content": { 

232 "application/json": { 

233 "schema": { 

234 "$ref": "#/components/schemas/HeroPublic" 

235 } 

236 } 

237 }, 

238 }, 

239 "422": { 

240 "description": "Validation Error", 

241 "content": { 

242 "application/json": { 

243 "schema": { 

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

245 } 

246 } 

247 }, 

248 }, 

249 }, 

250 }, 

251 }, 

252 }, 

253 "components": { 

254 "schemas": { 

255 "HTTPValidationError": { 

256 "title": "HTTPValidationError", 

257 "type": "object", 

258 "properties": { 

259 "detail": { 

260 "title": "Detail", 

261 "type": "array", 

262 "items": { 

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

264 }, 

265 } 

266 }, 

267 }, 

268 "HeroCreate": { 

269 "title": "HeroCreate", 

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

271 "type": "object", 

272 "properties": { 

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

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

275 "age": { 

276 "title": "Age", 

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

278 }, 

279 }, 

280 }, 

281 "HeroPublic": { 

282 "title": "HeroPublic", 

283 "required": ["name", "secret_name", "id"], 

284 "type": "object", 

285 "properties": { 

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

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

288 "age": { 

289 "title": "Age", 

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

291 }, 

292 "id": {"title": "Id", "type": "integer"}, 

293 }, 

294 }, 

295 "HeroUpdate": { 

296 "title": "HeroUpdate", 

297 "type": "object", 

298 "properties": { 

299 "name": { 

300 "title": "Name", 

301 "anyOf": [{"type": "string"}, {"type": "null"}], 

302 }, 

303 "secret_name": { 

304 "title": "Secret Name", 

305 "anyOf": [{"type": "string"}, {"type": "null"}], 

306 }, 

307 "age": { 

308 "title": "Age", 

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

310 }, 

311 }, 

312 }, 

313 "ValidationError": { 

314 "title": "ValidationError", 

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

316 "type": "object", 

317 "properties": IsOneOf( 

318 { 

319 "loc": { 

320 "title": "Location", 

321 "type": "array", 

322 "items": { 

323 "anyOf": [ 

324 {"type": "string"}, 

325 {"type": "integer"}, 

326 ] 

327 }, 

328 }, 

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

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

331 }, 

332 { 

333 "loc": { 

334 "title": "Location", 

335 "type": "array", 

336 "items": { 

337 "anyOf": [ 

338 {"type": "string"}, 

339 {"type": "integer"}, 

340 ] 

341 }, 

342 }, 

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

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

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

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

347 }, 

348 ), 

349 }, 

350 } 

351 }, 

352 }