news 2026/10/17 2:27:05

ade-python测试体系指南:respx Mock、contract契约测试与surface-lock门禁实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ade-python测试体系指南:respx Mock、contract契约测试与surface-lock门禁实战

【免费下载链接】ade-python

Python library for Agentic Document Extraction (ADE).

项目地址:https://gitcode.com/gh_mirrors/ade/ade-python
点击查看免费下载

ade-python 是 LandingAI 的Agentic Document Extraction(ADE)Python SDK,用于文档解析、结构化抽取与 grounding 对齐。它的测试体系由三层组成:respx 离线 Mock 测试、contract 契约测试和surface-lock 发布门禁,共同保证 SDK 与上游网关的契约始终一致。本文带你完整走一遍这三层测试的设计思路与运行方式。🧪

测试体系全景:四层金字塔

ade-python 的测试不是"一套用例跑到底",而是按可信度分层,各层职责清晰:

层级位置覆盖内容是否需要凭证
响应模型tests/test_v2_types.pyV2ParseResponse/V2ExtractResult等模型的反序列化、未知字段容错❌
任务归一化tests/test_v2_normalize.py上游任务信封 → 统一Job的转换❌
respx Mock 资源层tests/api_resources/v2/主机路由、multipart/JSON 请求体、轮询逻辑❌
Live 契约测试tests/contract/test_v2_smoke.py对 staging 环境的端到端真实调用✅

分层设计带来一个直接好处:rye run pytest的默认运行永远不会碰真实环境。在 pyproject.toml 中,addopts写死了--tb=short -n auto -m 'not contract and not production',契约测试和 production 测试都是显式开启的。

respx Mock 测试:不发一个网络请求的 HTTP 断言

respx 是 httpx 的 Mock 库。ade-python 在 tests/api_resources/v2/ 下大量使用@respx.mock装饰器,把 SDK 的每次请求都拦截在本地,实现对请求内容(而不只是响应)的精确断言。

以 parse 接口为例,test_parse.py 展示了典型的断言方式:

@respx.mock def test_parse_sync_ok_routes_to_v2_and_sends_options_json() -> None: client = LandingAIADE(apikey=APIKEY, environment="production") route = respx.post("https://api.ade.landing.ai/v2/parse").mock( return_value=httpx.Response(200, json=PARSE_BODY) ) result = client.v2.parse(document=b"pdf", model="dpt-3-latest", options={"foo": "bar"}) # options 必须以 JSON 编码的字符串表单字段发送 sent = route.calls.last.request.content assert b'{"foo": "bar"}' in sent

这里的关键技巧是检查发出去的字节流:

  • 路由是否正确:断言请求打到了https://api.ade.landing.ai/v2/parse而不是 V1 主机;
  • multipart 字段是否干净:未设置的Omit/NotGiven哨兵值绝不能以"<...Omit object...>"或"NOT_GIVEN"字面量泄漏进请求体;
  • 敏感信息如何折叠:password=参数只能落入options.password,test_parse_sync_folds_password_into_options 专门钉死这一行为,因为第二份副本会让密钥双重暴露。

@respx.mock还带来一个隐性收益:它是密闭(hermetic)的——没有注册路由的请求会直接失败,所以"URL 写错"这类回归无法溜过 CI。

一个实现细节:respx 不支持自定义 transport,因此 conftest.py 会自动跳过"aiohttp 客户端 + respx_mock"组合的测试用例,避免这类用例永远报错。

contract 契约测试:对 staging 的真实环境断言

Mock 测试验证的是"SDK 认为正确的行为",而 contract 测试验证的是"staging 上真实发生的行为"。它位于 tests/contract/,全部用例打上pytest.mark.contract标记,只有导出LANDINGAI_ADE_STAGING_APIKEY才会运行:

LANDINGAI_ADE_STAGING_APIKEY=... rye run pytest tests/contract/test_v2_smoke.py -m contract

contract/test_v2_smoke.py 里有几处很值得新手学习的设计:

  • 快速失败优先:SDK 默认 8 分钟超时 + 2 次重试,这对解析 500 页扫描件是合理的,但对"合并门禁"是灾难——一个卡住的端点会烧掉约 24 分钟。所以契约测试把单次请求压到CONTRACT_TIMEOUT = 45.0秒且max_retries=0,让"staging 没响应"直接以APITimeoutError的醒目形式暴露,而不是伪装成"套件很慢"。
  • 断言行为而非状态码:例如grounding=False的抽取测试不断言 2xx,而是断言返回的ranges全部为null——因为"参数没到线上"在 staging 上不会报错,只会静默地照常 grounding。
  • 用真实 PDF 跑 parse:套件自带 tests/contract/sample.pdf 作为两页样本文件,保证 parse 路径走的是真实的 PDF 解码。

V1 侧的契约测试在 tests/contract/test_v1_smoke.py 与 test_v1_production.py,后者打production标记、消耗真实生产环境额度,只由专门的 CI 作业触发。

surface-lock 门禁:锁定已发布的公共 API

ade-python 的模型代码由 OpenAPI 规范自动生成,AI 可以参与"接线",但向后兼容的保证由 CI 强制执行——这就是 surface-lock 门禁的意义。

scripts/spec-sync/surface-lock.sh 的工作流程:

  1. 确定基线:用git describe --tags找到最后一个 release tag。基线是"已发布的表面",而不是 main 上一个 commit——已合并但未发布的接口允许继续变化,只有发布出去的承诺才被锁定;
  2. 对比检查:运行griffe check landingai_ade --against <baseline> --search src,逐行报告破坏性变更;
  3. 豁免加法变更:公共常量的值变更(比如ENVIRONMENTS映射新增一项)被识别为加法配置而非签名破坏,自动放行;
  4. 真正的破坏则失败:剩余任何一行都视为 API 破坏,脚本退出码非 0,PR 被拦截。

发布路径上还有第二道锁:scripts/spec-sync/release-gate.sh 会把本地提交的 V1 快照与生产环境的实时 OpenAPI 规范逐(path, method)对比——SDK 实现了但生产还没有的路由会挡住发布,防止 staging-only 功能提前上车。

围绕规范同步的完整工具链都在 scripts/spec-sync/ 下:

脚本作用
check-drift.sh拉取线上规范并与本地快照 diff;exit 10 表示有漂移
fetch-normalize.sh拉取并规范化 OpenAPI 规范
gen-models.sh用 datamodel-codegen 从快照生成参考模型到 specs/_generated/
surface-lock.sh已发布 API 的破坏性变更门禁
release-gate.sh"已实现路由必须存在于生产"门禁
notify-new-drift.sh检测到新漂移时向同步 PR 发通知(含去重)

本地运行测试:速查清单

🚀 三条命令覆盖日常所有场景:

# 1. 离线套件(模型 + 归一化 + respx Mock),无需任何凭证 rye run pytest tests/test_v2_types.py tests/test_v2_normalize.py tests/api_resources/v2 # 2. 契约测试(需要 staging 密钥) LANDINGAI_ADE_STAGING_APIKEY=... rye run pytest tests/contract/test_v2_smoke.py -m contract # 3. pydantic v1 兼容会话 rye run nox -s test-pydantic-v1

其中 nox 会话定义在 noxfile.py,会额外安装pydantic<2以验证旧版本兼容。

规范变更时的测试更新流程

当上游规范(specs/v2-aide.json)发生变化,docs/v2-testing.md 给出固定四步:

  1. 阅读机械 diff(specs/v2-aide.json与 specs/_generated/v2_models.py);
  2. 加法型请求字段→ 变成run/create方法上新的可选关键字参数(仅限requestBody顶层属性);
  3. 加法型响应字段→ 加入 src/landingai_ade/types/v2/ 对应模型,被删除/改名的字段保留为可选以保证向后兼容;
  4. 在 tests/api_resources/v2/ 补 respx 测试,在 tests/contract/test_v2_smoke.py 补一条 live 断言,最后更新 api.md 与测试指南。

小结:为什么这套体系对新手友好

  • 默认离线:平时写代码只需rye run pytest,秒级反馈、零凭证、零外部依赖;
  • 分层可信:Mock 层钉死"SDK 的行为",契约层验证"环境的真实行为",两层各有分工、互不替代;
  • 门禁代替自觉:surface-lock 与 release-gate 把"不许破坏已发布 API"从口头约定变成 CI 里的一条退出码,让自动化改动(包括 AI 参与的接线)也能安全合并。

理解这三层之后,你再去看 CONTRIBUTING.md 中的贡献流程,整个 spec-sync 流水线就会顺理成章了。🔒

【免费下载链接】ade-python

Python library for Agentic Document Extraction (ADE).

项目地址:https://gitcode.com/gh_mirrors/ade/ade-python
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/17 2:24:31

基于MP2642GR-Z与STM32F373RC的串联电芯被动均衡设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/17 2:24:24

Qwen-Image-2.1开源图像编辑模型:本地部署与ComfyUI工作流实战指南

1. 这次开源到底放了什么料Qwen-Image-2.1 开源发布这件事&#xff0c;我第一反应不是去看榜单&#xff0c;而是先去翻它的模型卡和权重文件。原因很简单&#xff0c;图像编辑这个赛道&#xff0c;榜单排名和实际手感经常是两回事。Arena 图像编辑榜开源第一这个成绩确实亮眼&a…

作者头像 李华
网站建设 2026/10/17 2:23:04

VTK像素拾取完全指南:选择器选型与坐标换算实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/17 2:21:20

ComfyUI工作流排错:节点依赖、缺失模型与循环链路检查

项目编号&#xff1a;20260728-019。本文代码、测试、文档与示例数据均为独立编写&#xff0c;不包含榜单项目源码或受限素材。为什么需要这个工具 读取ComfyUI风格工作流JSON&#xff0c;提取节点依赖、检测缺失引用和孤立节点&#xff0c;汇总模型文件清单并生成HTML报告。实…

作者头像 李华