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

51 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2026-01-06 21:09 +0000

1import importlib 1jklmnopqr

2from types import ModuleType 1jklmnopqr

3 

4import pytest 1jklmnopqr

5from fastapi.testclient import TestClient 1jklmnopqr

6from sqlmodel import create_engine 1jklmnopqr

7from sqlmodel.pool import StaticPool 1jklmnopqr

8 

9from tests.conftest import needs_py310 1jklmnopqr

10 

11 

12@pytest.fixture( 1jklmnopqr

13 name="module", 

14 params=[ 

15 pytest.param("tutorial001_py39"), 

16 pytest.param("tutorial001_py310", marks=needs_py310), 

17 ], 

18) 

19def get_module(request: pytest.FixtureRequest) -> ModuleType: 1jklmnopqr

20 mod = importlib.import_module(f"docs_src.tutorial.fastapi.update.{request.param}") 1jklmnopqr

21 mod.sqlite_url = "sqlite://" 1jklmnopqr

22 mod.engine = create_engine( 1jklmnopqr

23 mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool 

24 ) 

25 return mod 1jklmnopqr

26 

27 

28def test_tutorial(module: ModuleType): 1jklmnopqr

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

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

31 hero2_data = { 1abcdefghi

32 "name": "Spider-Boy", 

33 "secret_name": "Pedro Parqueador", 

34 "id": 9000, 

35 } 

36 hero3_data = { 1abcdefghi

37 "name": "Rusty-Man", 

38 "secret_name": "Tommy Sharp", 

39 "age": 48, 

40 } 

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

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

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

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

45 hero2 = response.json() 1abcdefghi

46 hero2_id = hero2["id"] 1abcdefghi

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

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

49 hero3 = response.json() 1abcdefghi

50 hero3_id = hero3["id"] 1abcdefghi

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

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

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

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

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

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

57 data = response.json() 1abcdefghi

58 assert len(data) == 3 1abcdefghi

59 

60 response = client.patch( 1abcdefghi

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

62 ) 

63 data = response.json() 1abcdefghi

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

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

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

67 "The secret name should be updated" 

68 ) 

69 

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

71 data = response.json() 1abcdefghi

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

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

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

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

76 ) 

77 

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

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

80 

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

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

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

84 "openapi": "3.1.0", 

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

86 "paths": { 

87 "/heroes/": { 

88 "get": { 

89 "summary": "Read Heroes", 

90 "operationId": "read_heroes_heroes__get", 

91 "parameters": [ 

92 { 

93 "required": False, 

94 "schema": { 

95 "title": "Offset", 

96 "type": "integer", 

97 "default": 0, 

98 }, 

99 "name": "offset", 

100 "in": "query", 

101 }, 

102 { 

103 "required": False, 

104 "schema": { 

105 "title": "Limit", 

106 "maximum": 100.0, 

107 "type": "integer", 

108 "default": 100, 

109 }, 

110 "name": "limit", 

111 "in": "query", 

112 }, 

113 ], 

114 "responses": { 

115 "200": { 

116 "description": "Successful Response", 

117 "content": { 

118 "application/json": { 

119 "schema": { 

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

121 "type": "array", 

122 "items": { 

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

124 }, 

125 } 

126 } 

127 }, 

128 }, 

129 "422": { 

130 "description": "Validation Error", 

131 "content": { 

132 "application/json": { 

133 "schema": { 

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

135 } 

136 } 

137 }, 

138 }, 

139 }, 

140 }, 

141 "post": { 

142 "summary": "Create Hero", 

143 "operationId": "create_hero_heroes__post", 

144 "requestBody": { 

145 "content": { 

146 "application/json": { 

147 "schema": { 

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

149 } 

150 } 

151 }, 

152 "required": True, 

153 }, 

154 "responses": { 

155 "200": { 

156 "description": "Successful Response", 

157 "content": { 

158 "application/json": { 

159 "schema": { 

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

161 } 

162 } 

163 }, 

164 }, 

165 "422": { 

166 "description": "Validation Error", 

167 "content": { 

168 "application/json": { 

169 "schema": { 

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

171 } 

172 } 

173 }, 

174 }, 

175 }, 

176 }, 

177 }, 

178 "/heroes/{hero_id}": { 

179 "get": { 

180 "summary": "Read Hero", 

181 "operationId": "read_hero_heroes__hero_id__get", 

182 "parameters": [ 

183 { 

184 "required": True, 

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

186 "name": "hero_id", 

187 "in": "path", 

188 } 

189 ], 

190 "responses": { 

191 "200": { 

192 "description": "Successful Response", 

193 "content": { 

194 "application/json": { 

195 "schema": { 

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

197 } 

198 } 

199 }, 

200 }, 

201 "422": { 

202 "description": "Validation Error", 

203 "content": { 

204 "application/json": { 

205 "schema": { 

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

207 } 

208 } 

209 }, 

210 }, 

211 }, 

212 }, 

213 "patch": { 

214 "summary": "Update Hero", 

215 "operationId": "update_hero_heroes__hero_id__patch", 

216 "parameters": [ 

217 { 

218 "required": True, 

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

220 "name": "hero_id", 

221 "in": "path", 

222 } 

223 ], 

224 "requestBody": { 

225 "content": { 

226 "application/json": { 

227 "schema": { 

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

229 } 

230 } 

231 }, 

232 "required": True, 

233 }, 

234 "responses": { 

235 "200": { 

236 "description": "Successful Response", 

237 "content": { 

238 "application/json": { 

239 "schema": { 

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

241 } 

242 } 

243 }, 

244 }, 

245 "422": { 

246 "description": "Validation Error", 

247 "content": { 

248 "application/json": { 

249 "schema": { 

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

251 } 

252 } 

253 }, 

254 }, 

255 }, 

256 }, 

257 }, 

258 }, 

259 "components": { 

260 "schemas": { 

261 "HTTPValidationError": { 

262 "title": "HTTPValidationError", 

263 "type": "object", 

264 "properties": { 

265 "detail": { 

266 "title": "Detail", 

267 "type": "array", 

268 "items": { 

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

270 }, 

271 } 

272 }, 

273 }, 

274 "HeroCreate": { 

275 "title": "HeroCreate", 

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

277 "type": "object", 

278 "properties": { 

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

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

281 "age": { 

282 "title": "Age", 

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

284 }, 

285 }, 

286 }, 

287 "HeroPublic": { 

288 "title": "HeroPublic", 

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

290 "type": "object", 

291 "properties": { 

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

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

294 "age": { 

295 "title": "Age", 

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

297 }, 

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

299 }, 

300 }, 

301 "HeroUpdate": { 

302 "title": "HeroUpdate", 

303 "type": "object", 

304 "properties": { 

305 "name": { 

306 "title": "Name", 

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

308 }, 

309 "secret_name": { 

310 "title": "Secret Name", 

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

312 }, 

313 "age": { 

314 "title": "Age", 

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

316 }, 

317 }, 

318 }, 

319 "ValidationError": { 

320 "title": "ValidationError", 

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

322 "type": "object", 

323 "properties": { 

324 "loc": { 

325 "title": "Location", 

326 "type": "array", 

327 "items": { 

328 "anyOf": [{"type": "string"}, {"type": "integer"}] 

329 }, 

330 }, 

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

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

333 }, 

334 }, 

335 } 

336 }, 

337 }