pytest中模拟文件上传必须用requests的files参数构造RFC 7578合规的multipart/form-data请求体,不可用raw bytes或data参数;需以三元组格式传入文件名、二进制文件对象和MIME类型,并配合data参数提交其他表单字段。

pytest里怎么模拟文件上传的multipart/form-data请求
直接用 requests.post 发 raw bytes 或字符串是行不通的——服务端会解析失败,报 MultiPartParserError 或空文件。必须让 pytest 测试用例生成符合 RFC 7578 的 multipart body,关键靠 requests 自带的 files 参数,不是 data。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 用
files={"file": ("test.pdf", open("test.pdf", "rb"), "application/pdf")},三元组格式:字段名、(文件名, 文件对象, MIME类型) - 不要提前
.read()文件内容再传进去,否则requests无法设置 boundary 和 Content-Disposition - 测试完记得
close()文件对象,或改用with open(...) as f:上下文管理 - 如果接口还带其他表单字段(如
user_id),统一塞进data参数:data={"user_id": "123"},和files并列传入
如何在pytest中安全读取测试用的二进制文件
硬编码相对路径(如 "./tests/data/test.jpg")容易因 pytest 工作目录变化而报 FileNotFoundError。不能依赖 os.getcwd(),得用模块级路径定位。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 用
pathlib.Path(__file__).parent / "data" / "test.png"获取当前测试文件同级的资源目录 - 检查文件是否存在:
if not test_file.exists(): pytest.skip("missing test file") - 避免在
conftest.py里全局 open 文件句柄——pytest 多进程运行时会冲突,每次测试都应独立打开/关闭 - 小文件可考虑用
io.BytesIO(b"\x89PNG\r\n...")构造内存文件,跳过磁盘 I/O,也方便做损坏文件等异常场景测试
上传失败时怎么断言具体错误原因而不是只看状态码
很多测试只写 assert resp.status_code == 400,但掩盖了真实问题:是文件太大?类型不被允许?还是 JSON 解析失败导致的 500?必须解析响应体。
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 先确保响应是 JSON:
assert resp.headers.get("content-type", "").startswith("application/json") - 再解析:
resp.json(),然后断言字段,比如assert resp.json()["detail"] == "Unsupported file type" - 对非 JSON 响应(如纯文本 500 错误页),用
resp.text+in判断关键词,例如assert "max_size" in resp.text - 别忽略
resp.raise_for_status()——它会在 4xx/5xx 时抛异常,反而让 pytest 报错信息更干净
pytest参数化上传不同文件类型/大小时要注意什么
用 @pytest.mark.parametrize 跑多组上传测试很常见,但大文件(比如 100MB)会导致测试变慢、临时目录爆满、CI 超时。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 把“大文件”测试单独标记,例如
@pytest.mark.slow,CI 默认跳过,本地调试时加-m "not slow" - 用
tempfile.NamedTemporaryFile(suffix=".csv", delete=False)动态生成测试文件,测完手动os.unlink(),避免残留 - 参数化时避免直接传文件对象(会 pickle 失败),改为传路径字符串或生成函数
- 注意 Flask/FastAPI 默认的
MAX_CONTENT_LENGTH或upload_max_filesize(Nginx)限制,测试前确认服务端配置已调高
边界情况比想象中多:空文件、超长文件名、含中文路径、Content-Type 被客户端伪造……真正卡住的往往不是代码逻辑,而是 multipart 边界符没对齐,或者测试文件没按二进制模式打开。

















