大多数 API 团队到最后都会落进同一种别扭分裂里。一个请求在 curl 里调通,另一个请求留在 GUI 集合里,登录状态靠临时脚本重造,最后真正进 CI 的又常常是第四个版本,写在另一个测试框架中。Hurl 有意思,就在于它试图把这些层收回到同一个产物里。它在官方首页上的定义很朴素:一个命令行工具,用纯文本格式定义并执行 HTTP 请求,还能串联请求、捕获值,并对响应头和响应体做查询判断,覆盖 HTML、REST、SOAP、GraphQL 以及其他 XML/JSON API。[1]
这句话看上去不张扬,细看当下的项目状态,轮廓就清楚起来了。以 2026-05-03T02:40:00Z UTC 为准,GitHub API 显示 Orange-OpenSource/hurl 有 18,865 个 stars、721 个 forks、197 个 open issues,最近一次 push 时间是 2026-05-02T20:15:06Z。[5] 最新标签版是 8.0.1,发布于 2026-04-29;紧挨着它的 8.0.0 则带来了 raw multiline strings、新的 RFC 9535 JSONPath 模块,以及更多证书查询能力。[6][7] 这些数字本身还不能自动说明它适合每个团队,却已经足以说明,这个项目的格式与边界值得被认真读一遍,草草归到“又一个 HTTP 客户端”那一栏,会漏掉它真正的设计重点。
Thoughtworks 在 2025 年 4 月的 Technology Radar 里给出的概括很到位:Hurl 是一个处理 HTTP 请求序列的“Swiss Army knife”,既适合自动化,也适合自动化 API 测试,而且测试文件本身可以直接放进代码仓库。[8] 这个框架是对的。Hurl 真正值得讨论的地方,落在它让 HTTP 行为可以和依赖它的代码一起被审阅;curl 的漂亮包装,只是很浅的一层表象。
配图说明:题图有意避开界面截图,把文章放回仓库原生测试的日常工作现场:开发者的桌面、终端式操作和放在代码旁边的记录共同构成真实语境。这个场景适合本文重心,因为 Hurl 的价值显现在 HTTP 会话成为文件之后,开发者可以阅读、比较、执行并审阅这份契约。[1]
文件本身就是契约
Hurl 最核心的设计动作,是把一个文本文件同时当成请求脚本与响应预期。首页描述的是一种可以执行请求、把多个请求串起来、捕获值并验证结果的格式。[1] 这意味着它真正有用的单位,已经从“一个请求标签页”或“一个保存过的 collection entry”,转向一份可以被版本控制的 .hurl 文件。它可以跟着服务走,跟着网关走,跟着测试夹具走,也可以跟着运维 runbook 一起走。
这种仓库原生的形状,会直接改变评审的成本。队友要看登录流程、健康检查序列,或者某个回归 case,可以离开独立 GUI 导出文件,直接把文本读完。Thoughtworks 从外部也强调了同一个点:Hurl 测试可以保存在代码仓库里,而这种简洁性正是它的吸引力之一。[8] 放在实际团队里,这使 Hurl 对那些希望把 HTTP 行为纳入 diff 和 code review 的团队尤其有说服力。
这件事在 2026 更重要,是因为很多 API 表面早已不止一条 JSON 调用。它们带着重定向、认证头、cookie 状态、HTML 握手,以及内部和外部网关混在一起的路径。Hurl 的格式窄到还能保持可读,宽到又足以把这些步骤放进同一个文件里。[1] 和把同一段流程散落在 shell 历史、浏览器标签页、测试框架 helper 之间相比,这是一种更可靠的组织方式。
捕获机制让多步会话保持线性
一旦把 captures 放进来,Hurl 就不再只是 curl 的文本版本。官方 captures 教程展示的是一个很具体的场景:先用 XPath 从 HTML 登录页里提取 CSRF token,把它存进变量,再在后续 POST 请求里复用这个值。[2] 同一个教程也顺手交代了更大的规则:captures 和 asserts 共用查询语言,所以无论值来自 HTML、JSON、cookie,还是别的响应表面,处理它们时的思路都保持一致。[2]
这正是它能进入真实会话测试的原因,价值范围已经超过单次调用演示。一个登录序列、一条重定向链、一个两步 API 工作流,都能沿着线性顺序留在文件中。先读第一个请求,再看捕获了什么,接着读第二个消耗它的请求。captures 教程还特别说明,Hurl 默认不会 自动跟随重定向,因此每一步都可以被明确执行和检查。[2] 这个选择很能说明它的气质。Hurl 没有打算把协议行为藏进便捷魔法里,它希望 HTTP 对话本身始终处在视野中。
对运维团队和应用团队来说,这种可见性往往就是核心价值。若一个网关突然返回了错误的 Location 头,或者 HTML 表单里不再暴露自动化所依赖的 token 字段,一份纯文本测试就该在协议真正改变的地方断掉。Hurl 的 capture 模型,让这种失败非常容易定位。[2]
断言与报告,让它真正进入 CI
第二个关键设计动作,是 Hurl 把响应检查写成一等语法,让它离开围在请求旁边的注释位置。asserting-response 文档列出了对状态码、响应头、响应体、bytes、XPath、JSONPath、regex、URL、redirects、IP address、duration、variables 以及 SSL certificate 值的检查能力。[3] 这件事重要,是因为它让同一个文件能一直贴着协议表面走。你既能检查 HTTP 结果,也能检查 payload 结构,还能顺手检查一部分传输层细节,整套检查因此先停留在 HTTP 会话自身的文本边界内。[3]
测试面把这件事补完了。running-tests 文档说明了 --test 模式的测试输出,还提供 HTML 和 JSON 报告;手册里则记录了 JUnit 报告能力。[4] 同一份测试文档还提到,HTML 报告会把输入的 Hurl 文件以渲染后的形式收进去,JSON 报告则会保留结构化执行结果供后续处理。[4] 换一种说法,Hurl 的目标并不止于“这条请求能跑通”,它更进一步,把请求文件推进成 CI 产物。
在小型和中型集成测试套件里,这件事尤其实际。团队可以把请求文件放在服务代码旁边,通过支持的 HURL_VARIABLE_... 机制注入环境变量,用 --test 执行,再把 HTML 或机器可读报告挂进流水线。[4] 这比长期维护一套只适合人工探索的 API 客户端标签页,再额外补一套只给流水线看的测试代码,要干净得多。
它的边界,来自它有意保持狭窄
Hurl 最强的地方,是那些真正需要把 HTTP 交换过程保存下来的场景。登录序列、smoke tests、网关检查、带有响应断言的契约式回归,以及那些协议细节比应用侧控制流更重要的 case,都很适合它。[1][2][3][4] 把官方文档和 Thoughtworks 的外部判断放在一起,会指向同一个结论:Hurl 的优势,就建立在产物足够小、足够文本化、足够可审阅这一点上。[1][8]
也正因为如此,它的上限同样很清楚。Hurl 没有打算变成一套通用编程 harness,没有打算变成一个庞大的协作式 GUI 工作台,也没有打算替换掉平台团队手里所有基于属性、基于负载、基于复杂编排的测试系统。它的价值,恰恰来自对那种膨胀的克制。若你的问题需要重分支逻辑、大规模合成数据生成,或者很深的自定义编排,你最后还是会回到通用语言或另一类测试系统中去。可如果你真正要钉住的是一段带精确检查的 HTTP 会话,那么 Hurl 的狭窄会转化成一种强项。
这也就是 Hurl 在 2026 值得写一篇项目导读的原因。眼前真正活着的想法,落在请求顺序、捕获状态、断言和报告共同收进一个被版本控制的产物里,HTTP 行为由此更容易被团队拥有。[1][2][3][4][8] 从当前发布节奏与上游活跃度来看,这套设计已经远远超过了新鲜玩具的阶段。[5][6][7]
来源
- Hurl 首页:项目概览、纯文本请求格式、请求串联、captures、assertions,以及对 HTML、REST、SOAP、GraphQL 和其他 XML/JSON API 的覆盖范围。
- Hurl Docs,《Captures》:多请求串联、用 XPath 捕获 CSRF token、变量复用,以及显式处理重定向。
- Hurl Docs,《Asserting Response》:支持的断言类型,包括 headers、XPath、JSONPath、regex、redirects、duration 和 SSL certificate 检查。
- Hurl Docs,《Running Tests》与手册报告选项:
--test、HTML/JSON 报告、报告中渲染输入文件,以及通过HURL_VARIABLE_...注入环境变量。 Orange-OpenSource/hurl的 GitHub API 快照:文章创建时的 stars、forks、open issues、default branch 以及最近 push/update 时间。- Hurl
8.0.1的 GitHub release 页面:最新标签版与发布时间。 - Hurl
8.0.0的 GitHub release 页面:raw multiline strings、RFC 9535 JSONPath 支持,以及 8.x 变化的发布说明基线。 - Thoughtworks Technology Radar,《Hurl》:从外部把 Hurl 视作纯文本请求序列与自动化 API 测试工具,并强调测试文件可直接放进代码仓库。