Coverage for tests / test_request_params / test_file / test_list.py: 100%

122 statements  

« prev     ^ index     » next       coverage.py v7.13.3, created at 2026-04-06 01:24 +0000

1from typing import Annotated 1abcd

2 

3import pytest 1abcd

4from fastapi import FastAPI, File, UploadFile 1abcd

5from fastapi.testclient import TestClient 1abcd

6 

7from .utils import get_body_model_name 1abcd

8 

9app = FastAPI() 1abcd

10 

11# ===================================================================================== 

12# Without aliases 

13 

14 

15@app.post("/list-bytes", operation_id="list_bytes") 1abcd

16async def read_list_bytes(p: Annotated[list[bytes], File()]): 1abcd

17 return {"file_size": [len(file) for file in p]} 1efgh

18 

19 

20@app.post("/list-uploadfile", operation_id="list_uploadfile") 1abcd

21async def read_list_uploadfile(p: Annotated[list[UploadFile], File()]): 1abcd

22 return {"file_size": [file.size for file in p]} 2i Nbj k

23 

24 

25@pytest.mark.parametrize( 1abcd

26 "path", 

27 [ 

28 "/list-bytes", 

29 "/list-uploadfile", 

30 ], 

31) 

32def test_list_schema(path: str): 1abcd

33 openapi = app.openapi() 2ibjbkblbmbnbob

34 body_model_name = get_body_model_name(openapi, path) 2ibjbkblbmbnbob

35 

36 assert app.openapi()["components"]["schemas"][body_model_name] == { 2ibjbkblbmbnbob

37 "properties": { 

38 "p": { 

39 "type": "array", 

40 "items": { 

41 "type": "string", 

42 "contentMediaType": "application/octet-stream", 

43 }, 

44 "title": "P", 

45 }, 

46 }, 

47 "required": ["p"], 

48 "title": body_model_name, 

49 "type": "object", 

50 } 

51 

52 

53@pytest.mark.parametrize( 1abcd

54 "path", 

55 [ 

56 "/list-bytes", 

57 "/list-uploadfile", 

58 ], 

59) 

60def test_list_missing(path: str): 1abcd

61 client = TestClient(app) 1IJKLMNOP

62 response = client.post(path) 1IJKLMNOP

63 assert response.status_code == 422 1IJKLMNOP

64 assert response.json() == { 1IJKLMNOP

65 "detail": [ 

66 { 

67 "type": "missing", 

68 "loc": ["body", "p"], 

69 "msg": "Field required", 

70 "input": None, 

71 } 

72 ] 

73 } 

74 

75 

76@pytest.mark.parametrize( 1abcd

77 "path", 

78 [ 

79 "/list-bytes", 

80 "/list-uploadfile", 

81 ], 

82) 

83def test_list(path: str): 1abcd

84 client = TestClient(app) 1eifgjhk

85 response = client.post(path, files=[("p", b"hello"), ("p", b"world")]) 1eifgjhk

86 assert response.status_code == 200 1eifgjhk

87 assert response.json() == {"file_size": [5, 5]} 1eifgjhk

88 

89 

90# ===================================================================================== 

91# Alias 

92 

93 

94@app.post("/list-bytes-alias", operation_id="list_bytes_alias") 1abcd

95async def read_list_bytes_alias(p: Annotated[list[bytes], File(alias="p_alias")]): 1abcd

96 return {"file_size": [len(file) for file in p]} 1lmno

97 

98 

99@app.post("/list-uploadfile-alias", operation_id="list_uploadfile_alias") 1abcd

100async def read_list_uploadfile_alias( 1abcd

101 p: Annotated[list[UploadFile], File(alias="p_alias")], 

102): 

103 return {"file_size": [file.size for file in p]} 2p Obq r

104 

105 

106@pytest.mark.parametrize( 1abcd

107 "path", 

108 [ 

109 "/list-bytes-alias", 

110 "/list-uploadfile-alias", 

111 ], 

112) 

113def test_list_alias_schema(path: str): 1abcd

114 openapi = app.openapi() 2pbqbrbsbtbubvbwb

115 body_model_name = get_body_model_name(openapi, path) 2pbqbrbsbtbubvbwb

116 

117 assert app.openapi()["components"]["schemas"][body_model_name] == { 2pbqbrbsbtbubvbwb

118 "properties": { 

119 "p_alias": { 

120 "type": "array", 

121 "items": { 

122 "type": "string", 

123 "contentMediaType": "application/octet-stream", 

124 }, 

125 "title": "P Alias", 

126 }, 

127 }, 

128 "required": ["p_alias"], 

129 "title": body_model_name, 

130 "type": "object", 

131 } 

132 

133 

134@pytest.mark.parametrize( 1abcd

135 "path", 

136 [ 

137 "/list-bytes-alias", 

138 "/list-uploadfile-alias", 

139 ], 

140) 

141def test_list_alias_missing(path: str): 1abcd

142 client = TestClient(app) 1QRSTUVWX

143 response = client.post(path) 1QRSTUVWX

144 assert response.status_code == 422 1QRSTUVWX

145 assert response.json() == { 1QRSTUVWX

146 "detail": [ 

147 { 

148 "type": "missing", 

149 "loc": ["body", "p_alias"], 

150 "msg": "Field required", 

151 "input": None, 

152 } 

153 ] 

154 } 

155 

156 

157@pytest.mark.parametrize( 1abcd

158 "path", 

159 [ 

160 "/list-bytes-alias", 

161 "/list-uploadfile-alias", 

162 ], 

163) 

164def test_list_alias_by_name(path: str): 1abcd

165 client = TestClient(app) 1YZ01234

166 response = client.post(path, files=[("p", b"hello"), ("p", b"world")]) 1YZ01234

167 assert response.status_code == 422 1YZ01234

168 assert response.json() == { 1YZ01234

169 "detail": [ 

170 { 

171 "type": "missing", 

172 "loc": ["body", "p_alias"], 

173 "msg": "Field required", 

174 "input": None, 

175 } 

176 ] 

177 } 

178 

179 

180@pytest.mark.parametrize( 1abcd

181 "path", 

182 [ 

183 "/list-bytes-alias", 

184 "/list-uploadfile-alias", 

185 ], 

186) 

187def test_list_alias_by_alias(path: str): 1abcd

188 client = TestClient(app) 1lpmnqor

189 response = client.post(path, files=[("p_alias", b"hello"), ("p_alias", b"world")]) 1lpmnqor

190 assert response.status_code == 200, response.text 1lpmnqor

191 assert response.json() == {"file_size": [5, 5]} 1lpmnqor

192 

193 

194# ===================================================================================== 

195# Validation alias 

196 

197 

198@app.post("/list-bytes-validation-alias", operation_id="list_bytes_validation_alias") 1abcd

199def read_list_bytes_validation_alias( 1abcd

200 p: Annotated[list[bytes], File(validation_alias="p_val_alias")], 

201): 

202 return {"file_size": [len(file) for file in p]} 1stuv

203 

204 

205@app.post( 1abcd

206 "/list-uploadfile-validation-alias", 

207 operation_id="list_uploadfile_validation_alias", 

208) 

209def read_list_uploadfile_validation_alias( 1abcd

210 p: Annotated[list[UploadFile], File(validation_alias="p_val_alias")], 

211): 

212 return {"file_size": [file.size for file in p]} 1wxyz

213 

214 

215@pytest.mark.parametrize( 1abcd

216 "path", 

217 [ 

218 "/list-bytes-validation-alias", 

219 "/list-uploadfile-validation-alias", 

220 ], 

221) 

222def test_list_validation_alias_schema(path: str): 1abcd

223 openapi = app.openapi() 2xbybzbAbBbCbDbEb

224 body_model_name = get_body_model_name(openapi, path) 2xbybzbAbBbCbDbEb

225 

226 assert app.openapi()["components"]["schemas"][body_model_name] == { 2xbybzbAbBbCbDbEb

227 "properties": { 

228 "p_val_alias": { 

229 "type": "array", 

230 "items": { 

231 "type": "string", 

232 "contentMediaType": "application/octet-stream", 

233 }, 

234 "title": "P Val Alias", 

235 }, 

236 }, 

237 "required": ["p_val_alias"], 

238 "title": body_model_name, 

239 "type": "object", 

240 } 

241 

242 

243@pytest.mark.parametrize( 1abcd

244 "path", 

245 [ 

246 "/list-bytes-validation-alias", 

247 "/list-uploadfile-validation-alias", 

248 ], 

249) 

250def test_list_validation_alias_missing(path: str): 1abcd

251 client = TestClient(app) 156789!#$

252 response = client.post(path) 156789!#$

253 assert response.status_code == 422 156789!#$

254 assert response.json() == { 156789!#$

255 "detail": [ 

256 { 

257 "type": "missing", 

258 "loc": [ 

259 "body", 

260 "p_val_alias", 

261 ], 

262 "msg": "Field required", 

263 "input": None, 

264 } 

265 ] 

266 } 

267 

268 

269@pytest.mark.parametrize( 1abcd

270 "path", 

271 [ 

272 "/list-bytes-validation-alias", 

273 "/list-uploadfile-validation-alias", 

274 ], 

275) 

276def test_list_validation_alias_by_name(path: str): 1abcd

277 client = TestClient(app) 1%'()*+,-

278 response = client.post(path, files=[("p", b"hello"), ("p", b"world")]) 1%'()*+,-

279 assert response.status_code == 422, response.text 1%'()*+,-

280 

281 assert response.json() == { 1%'()*+,-

282 "detail": [ 

283 { 

284 "type": "missing", 

285 "loc": ["body", "p_val_alias"], 

286 "msg": "Field required", 

287 "input": None, 

288 } 

289 ] 

290 } 

291 

292 

293@pytest.mark.parametrize( 1abcd

294 "path", 

295 [ 

296 "/list-bytes-validation-alias", 

297 "/list-uploadfile-validation-alias", 

298 ], 

299) 

300def test_list_validation_alias_by_validation_alias(path: str): 1abcd

301 client = TestClient(app) 1swtxuyvz

302 response = client.post( 1swtxuyvz

303 path, files=[("p_val_alias", b"hello"), ("p_val_alias", b"world")] 

304 ) 

305 assert response.status_code == 200, response.text 1swtxuyvz

306 assert response.json() == {"file_size": [5, 5]} 1swtxuyvz

307 

308 

309# ===================================================================================== 

310# Alias and validation alias 

311 

312 

313@app.post( 1abcd

314 "/list-bytes-alias-and-validation-alias", 

315 operation_id="list_bytes_alias_and_validation_alias", 

316) 

317def read_list_bytes_alias_and_validation_alias( 1abcd

318 p: Annotated[list[bytes], File(alias="p_alias", validation_alias="p_val_alias")], 

319): 

320 return {"file_size": [len(file) for file in p]} 1ABCD

321 

322 

323@app.post( 1abcd

324 "/list-uploadfile-alias-and-validation-alias", 

325 operation_id="list_uploadfile_alias_and_validation_alias", 

326) 

327def read_list_uploadfile_alias_and_validation_alias( 1abcd

328 p: Annotated[ 

329 list[UploadFile], File(alias="p_alias", validation_alias="p_val_alias") 

330 ], 

331): 

332 return {"file_size": [file.size for file in p]} 1EFGH

333 

334 

335@pytest.mark.parametrize( 1abcd

336 "path", 

337 [ 

338 "/list-bytes-alias-and-validation-alias", 

339 "/list-uploadfile-alias-and-validation-alias", 

340 ], 

341) 

342def test_list_alias_and_validation_alias_schema(path: str): 1abcd

343 openapi = app.openapi() 2FbGbHbIbJbKbLbMb

344 body_model_name = get_body_model_name(openapi, path) 2FbGbHbIbJbKbLbMb

345 

346 assert app.openapi()["components"]["schemas"][body_model_name] == { 2FbGbHbIbJbKbLbMb

347 "properties": { 

348 "p_val_alias": { 

349 "type": "array", 

350 "items": { 

351 "type": "string", 

352 "contentMediaType": "application/octet-stream", 

353 }, 

354 "title": "P Val Alias", 

355 }, 

356 }, 

357 "required": ["p_val_alias"], 

358 "title": body_model_name, 

359 "type": "object", 

360 } 

361 

362 

363@pytest.mark.parametrize( 1abcd

364 "path", 

365 [ 

366 "/list-bytes-alias-and-validation-alias", 

367 "/list-uploadfile-alias-and-validation-alias", 

368 ], 

369) 

370def test_list_alias_and_validation_alias_missing(path: str): 1abcd

371 client = TestClient(app) 1./:;=?@[

372 response = client.post(path) 1./:;=?@[

373 assert response.status_code == 422 1./:;=?@[

374 assert response.json() == { 1./:;=?@[

375 "detail": [ 

376 { 

377 "type": "missing", 

378 "loc": [ 

379 "body", 

380 "p_val_alias", 

381 ], 

382 "msg": "Field required", 

383 "input": None, 

384 } 

385 ] 

386 } 

387 

388 

389@pytest.mark.parametrize( 1abcd

390 "path", 

391 [ 

392 "/list-bytes-alias-and-validation-alias", 

393 "/list-uploadfile-alias-and-validation-alias", 

394 ], 

395) 

396def test_list_alias_and_validation_alias_by_name(path: str): 1abcd

397 client = TestClient(app) 1]^_`{|}~

398 response = client.post(path, files=[("p", "hello"), ("p", "world")]) 1]^_`{|}~

399 assert response.status_code == 422 1]^_`{|}~

400 

401 assert response.json() == { 1]^_`{|}~

402 "detail": [ 

403 { 

404 "type": "missing", 

405 "loc": [ 

406 "body", 

407 "p_val_alias", 

408 ], 

409 "msg": "Field required", 

410 "input": None, 

411 } 

412 ] 

413 } 

414 

415 

416@pytest.mark.parametrize( 1abcd

417 "path", 

418 [ 

419 "/list-bytes-alias-and-validation-alias", 

420 "/list-uploadfile-alias-and-validation-alias", 

421 ], 

422) 

423def test_list_alias_and_validation_alias_by_alias(path: str): 1abcd

424 client = TestClient(app) 2abbbcbdbebfbgbhb

425 response = client.post(path, files=[("p_alias", b"hello"), ("p_alias", b"world")]) 2abbbcbdbebfbgbhb

426 assert response.status_code == 422, response.text 2abbbcbdbebfbgbhb

427 

428 assert response.json() == { 2abbbcbdbebfbgbhb

429 "detail": [ 

430 { 

431 "type": "missing", 

432 "loc": ["body", "p_val_alias"], 

433 "msg": "Field required", 

434 "input": None, 

435 } 

436 ] 

437 } 

438 

439 

440@pytest.mark.parametrize( 1abcd

441 "path", 

442 [ 

443 "/list-bytes-alias-and-validation-alias", 

444 "/list-uploadfile-alias-and-validation-alias", 

445 ], 

446) 

447def test_list_alias_and_validation_alias_by_validation_alias(path: str): 1abcd

448 client = TestClient(app) 1AEBFCGDH

449 response = client.post( 1AEBFCGDH

450 path, files=[("p_val_alias", b"hello"), ("p_val_alias", b"world")] 

451 ) 

452 assert response.status_code == 200, response.text 1AEBFCGDH

453 assert response.json() == {"file_size": [5, 5]} 1AEBFCGDH