ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Bruno替代Postman:本地优先的API调试工具与Git工作流实战

Bruno替代Postman:本地优先的API调试工具与Git工作流实战 先说个我自己的场景。前阵子在一台临时借来的办公笔记本上排查线上接口问题机器里除了浏览器和数据库客户端什么都没装。我习惯性地打开Postman结果先是等了将近十秒才看到主界面然后右上角一直弹“登录以同步数据”我点跳过它又每隔一阵就弹一次。本来只想花两分钟发一个GET请求看返回结果被启动速度、登录引导和被界面上的各种入口晃花了眼。也是那次之后我开始认真找Postman的替代品最后被一个叫Bruno的本地API客户端留住了——安装包10MB左右启动不到1秒不用注册登录数据全部落在本地文件里。这篇文章就从我一星期的高频使用体验出发聊聊它到底做到了什么、和Postman相比哪些地方能打、哪些地方还差点意思。1. 先聊为什么放着 Postman 不用非要找替代品1.1 安装包与启动的原始体感Postman这些年在我机器上越来越臃肿这不是错觉。Windows版本的安装包动辄上百MB装完以后首次启动要初始化、要检查更新、要加载工作区冷启动5秒以上是常态遇上机器状态不好的时候十几秒也有。我平时接口调试频率很高尤其是改一个字段、重启一个服务就要反复发请求的场景每次等它启动都是一次煎熬。相比之下Bruno的Windows安装包只有10MB左右装完之后启动到界面可交互体感在1秒内。这个差距对一个“每天要开几十次”的工具来说几乎是颠覆性的。我自己的感受是Postman更像一个需要常驻重量级IDEBruno则像一个轻量编辑器点开就能写。它没有后台进程没有常驻托盘不用的时候就安安静静占着磁盘上的几MB空间用到的时候再唤出来。1.2 注册、登录与云端同步带来的隐性成本Postman从某个版本开始变得非常强调账号体系。即便你只想在本地用它也会不断引导你注册账号、登录工作区、开通云同步。这些引导本身不致命但叠加在每次启动上累积起来消耗的耐心相当可观。更关键的是有些公司内部接口直接调的是内网域名或者带着敏感的业务数据这些请求信息被同步到第三方云上本来就是一个潜在风险。为了调试方便把内部接口结构传到Postman的服务器上这件事很多团队其实心里是有疙瘩的。Bruno的思路则完全不同离线优先数据不出本地。它压根没有云同步功能也不需要账号。用户下载以后打开就能用创建集合、写请求、配环境变量全部在本地完成。数据文件是纯文本的存在你自己指定的项目目录里。对于有数据隐私要求的场景这个设计天然就是安全的。我第一次用的时候就感觉到这种“回归工具本质”的产品思路确实能打动一批被Postman账号体系烦了很久的人。1.3 团队协作模式的差异云端协作与 Git 工作流Postman的团队协作核心是工作区和云端集合好处是成员之间共享接口定义很方便坏处是它会催生出一套和写代码割裂的工作流——接口调试信息在Postman工作区里代码在Git仓库里两边互相不透明。评审流程更是基本没法做谁改了一个接口请求参数其他人根本看不见变更记录出了问题只能靠问。Bruno选择了另一条路接口集合就是一个普通的文件夹里面是.bru文本文件天然能被Git纳管。这意味着你和团队可以把接口定义和代码放在同一个仓库里改接口请求就像改代码一样走Merge Request在Code Review里就能看到某个请求的URL、Header、Body发生了哪些变化。这个体验对习惯了Git工作流的团队来说是很自然的接口文档不再是某个工具里的云端数据而是可以跟着项目版本走的第一方文件。后面我在第5章会专门讲它配合Git和CI的玩法。2. Bruno 的本地优先存储.bru 文件到底是个什么东西2.1 请求配置以纯文本文件落盘读起来像配置文件Bruno里的一个请求就是一个扩展名为.bru的纯文本文件。你把一个集合当作一个文件夹把不同的接口请求拆成不同文件目录层级就是集合里看到的列表层级。文件内容不是加密的二进制也不是内置SQLite后塞给你的“黑盒”而是类似下面这种一看就懂的配置结构meta { name: 获取用户列表 type: http seq: 1 } get { url: https://api.example.com/users body: none auth: none }带Header和测试脚本的请求会在这个基础上扩展比如headers { Content-Type: application/json Authorization: Bearer {{token}} } test { const data res.getBody(); if (res.status 200) { console.log(用户数量 data.length); } }在Postman里这些信息散落在界面各处的输入框里你很难直观地看出一个请求“到底配了什么”。在Bruno里它就是一份可以被任何人打开阅读的文本既能被人工审查也能被脚本处理。这种透明性带来的安心感是那种UI白底表单给不了的。2.2 集合、环境变量与目录结构如何映射到文件系统Bruno里的集合在文件系统层面就是一个普通目录。集合下可以再建子文件夹表示分组每个.bru文件就是一个请求。环境变量则单独存在另一个文件里大致长这样vars { baseUrl: https://dev-api.example.com token: dev-token-123 }你在请求里写{{baseUrl}}Bruno就会根据当前选中的环境动态替换。这种“环境变量独立成文件”的存储方式让多环境管理变得非常直接。我通常会把env.bru按环境拆开比如local.bru、dev.bru、prod.bru放在集合根目录的environments文件夹下切换环境就是下拉框里选一下。目录结构大致是这样的my-api/ ├── environments/ │ ├── local.bru │ └── dev.bru ├── 用户模块/ │ ├── 获取用户列表.bru │ └── 创建用户.bru └── 订单模块/ ├── 获取订单详情.bru └── 取消订单.bru这种组织方式的好处是你可以把集合目录嵌到代码仓库的某个子目录下比如docs/apis/跟着项目走。我见过不少团队把接口定义单独扔在一个Confluence页面里页面过期了也没人维护。换成Bruno之后接口定义就变成了代码仓库的一部分版本跟着代码走接口变更能在提交历史里一目了然。2.3 这种设计给团队协作带来的改变一旦接口定义变成文件团队协作的方式就有了质的变化。首先合并冲突可以解决了。Postman工作区里如果两个人同时改一个集合往往会出现互相覆盖的情况。而在Git里同一个.bru文件被两个人改了会引发标准的合并冲突你有机会看到冲突点并手动解决。虽然多了一步操作但这种“能看见冲突”的能力远比“静默覆盖”可控得多。其次是变更可追溯。接口请求从哪个版本开始改的URL谁在什么时候加了一个Header响应测试脚本是哪个MR引入的全都可以通过Git日志回查。对于接口治理要求比较高的团队这是一个非常大的加分项。我之前在团队里推过一次工作区共享集合后来发现没人记得集合哪个版本是稳定版本大家都在各自本地改来改去。用Bruno后接口定义有了和代码一致的版本线这个问题自然就消失了。3. 实测日常接口调试从下载到跑通一次完整请求3.1 下载、安装与首次启动的实际耗时我的第一感受从下载安装就开始了。Bruno官网提供Windows、macOS和Linux的安装包Windows下大概是10MB出头的exe下载几乎就是一瞬间。安装过程没有多余选项一路默认即可装完不要求重启、不要求登录桌面图标也不会自动弹出一堆欢迎页。双击启动我测了几次从点击图标到窗口出现并可以输入URL基本在0.6到0.8秒左右。这个速度在同类工具里确实是第一梯队。如果你在Ubuntu这类Linux发行版上用它体验也差不多。Bruno提供了AppImage和deb包下载后直接运行就能用。常用的Debian/Ubuntu系统上执行sudo dpkg -i安装deb包然后在应用列表里启动整套流程非常轻。对经常在Linux服务器环境里测接口的人来说这个工具比“装一个Electron全家桶”轻太多了。3.2 界面的中文切换路径很多人第一次打开Bruno会发现默认界面是英文虽然简单英文不难懂但对于习惯中文界面的测试同学来说切到中文会友好很多。Bruno本身是支持多语言的只要在设置里把语言切到简体中文再重启应用就生效。具体路径是打开设置Settings找到语言或本地化选项选择简体中文重启应用即可。要注意的是切换语言后请求方法名、Tab名称这类核心操作区都会变成中文但.bru文件内部的meta、get、post这些关键字仍然是英文。这是正常的因为这些关键字本质上是文件的语法标识需要保持稳定。你可能会不习惯请求里的URL配置区块是英文的但这就像写代码不会要求编译器用中文一样工具界面汉化清楚就可以了。3.3 从新建请求到验证一个 GET 接口我以一个常见场景为例从零开始创建一个获取用户列表的GET请求。打开Bruno后先新建一个Collection命名为“示例项目”然后在集合上右键新建Request输入请求名称“获取用户列表”。在右侧编辑区请求方法默认是GETURL填上接口地址然后点击发送。响应面板会立即展示状态码、响应时间和响应体。这里它比Postman更清爽的一点是没有那么多默认折叠的面板没有一打开就刷屏的“Collection Runner”“Mock Server”等引导卡片看到的就是纯粹的请求编辑区和响应区。发送一个简单GET请求从建集合到看结果整个流程下来一分钟都用不到。3.4 处理 POST 请求、请求体与鉴权 Header日常调试里POST请求比GET多很多。在Bruno里把请求方法切到POSTBody区域会有多种格式可选包括JSON、XML、Text、表单数据等。选JSON后它会自动补一个格式化编辑器写JSON的时候有缩进和语法配色手感还算舒服。然后在Headers里配置Content-Type和Authorization或者用环境变量引用{{token}}点击发送就能得到响应。这里有一个值得夸的细节Bruno对Cookie和Header的处理是显式的。Postman在很多版本里会把“自动生成的Header”和“你手动写的Header”混在一起展示有时候你明明只写了Content-Type它就自作主张给你加了一堆东西。Bruno默认比较克制你写什么就是什么解决问题的时候干扰更少。当然这也意味着它不会帮你自动管理Cookie需要手动维护后面我会在踩坑部分提到这一点。4. 高频场景逐一验证导入迁移、SOAP调用、断言与取值4.1 从 Postman 迁移过来集合导入是否无缝很多人换工具最大的顾虑是我在Postman里的几百个接口能不能一键迁过来。Bruno在Import菜单里支持导入Postman的Collection文件具体格式是Postman导出的Collection JSON。导入后请求方法、URL、Headers、Body这些基础信息基本都能还原。我实测了一个包含37个请求的集合导入后大约有九成请求可以直接发送剩余的偏差主要出现在Postman脚本或启用状态的设置上。所以如果你是Postman老用户不用担心迁移成本。把Postman集合导出成JSON文件在Bruno里选择Import选择文件就能在本地生成一套对应的.bru文件。导入后建议逐个检查带脚本的请求尤其是依赖Postman内置变量和动态函数的脚本因为两边的脚本API不同不能直接互换。其余大部分纯请求配置是可以平滑过渡的。4.2 导出 curl 命令与多种语言代码片段大家在Postman里常用“Export as curl”把请求复制到命令行里用。Bruno同样有请求导出功能在请求编辑区可以直接导出为curl命令或者生成其他语言的代码片段比如Python的requests、JavaScript的fetch等。我实测导出curl的格式是比较标准的带Header和Body时会把引号转义处理好拿过去在终端里执行基本能一次跑通。这个能力在排查SSH远程问题的时候特别有用。很多线上问题需要在服务器本机发请求复现我一般先在Bruno里调好一个成功的请求然后用导出curl的方式拿到服务器上执行。对比两边请求差别再逐步排查。Bruno生成代码片段的能力虽然不像Postman支持那么多语言但对于常用的JavaScript、Python、Go、Java场景覆盖面足够。4.3 WebService(SOAP) 接口怎么调用说一个经常有人问的场景WebService接口怎么测。Postman本身也不直接支持生成SOAP信封或WSDL解析它也只是把一个SOAP请求当成普通的POST来处理。在Bruno里用法基本一致新建一个POST请求URL填WebService的EndPoint地址Headers里设置Content-Type: text/xml; charsetutf-8如果服务要求SOAPAction则再加一个SOAPAction头Body区域选XML并把完整的SOAP Envelope粘进去。例如请求一个查询天气的WebServiceBody里的大致结构是?xml version1.0 encodingutf-8? soap:Envelope xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xmlns:xsdhttp://www.w3.org/2001/XMLSchema xmlns:soaphttp://schemas.xmlsoap.org/soap/envelope/ soap:Body getWeather xmlnshttp://example.com/ citybeijing/city /getWeather /soap:Body /soap:Envelope发送后Bruno会把SOAP响应XML展示在响应面板里。因为响应体是XML它不会像JSON那样做格式化树不过有语法高亮和折叠人工阅读和复制提取关键字段没问题。如果你要断言SOAP响应里的某个节点值就在测试脚本里用字符串匹配或正则取值。4.4 断言、提取返回值与接口自动化测试接口调试只是基本功真正体现工具价值的是自动化测试。Bruno提供了一套基于JavaScript的脚本能力核心是用test块来写断言。常见的用法是发送请求后检查HTTP状态码、校验响应体字段、提取某个返回值赋给环境变量。比如一个登录接口获取返回的token并写入环境变量脚本大致是这样test { const data res.getBody(); if (data.code 0) { setEnvVar(token, data.data.token); test(登录成功, function() { expect(res.status).to.equal(200); }); } }注意这里的setEnvVar是Bruno的脚本接口作用是动态更新当前环境变量。这在连续接口调用里非常有用先用登录接口拿到token后续的业务请求直接通过{{token}}引用。对于一次登录、多次请求的业务链路测试这个机制可以把繁琐的“手动复制token”流程完全省掉。Bruno对断言的结果展示也比较直观测试脚本运行后响应区会显示通过/失败的测试用例列表。虽然它的脚本API比Postman的pm库要精简但常用的断言、变量写入、请求日志打印都有对应实现。做日常的接口冒烟测试和基础自动化验证是完全够的。5. 用一条命令跑测试CLI 与 CI 集成的进阶玩法5.1 bru CLI让接口测试进入命令行时代Bruno最有价值的进阶能力我觉得是命令行工具bru。它随桌面版安装也可以在CI环境单独安装。它的作用是直接在终端里运行集合中的请求和测试脚本输出测试报告。这意味着你在Bruno里写好的接口测试用例不只是“在图形界面里手点”而是能被脚本调用、被流水线执行。基本用法非常直接。在集合根目录下执行bru run它会遍历当前集合中的所有请求并执行一遍。如果只想跑某个文件夹下或某个标签的请求可以加上过滤参数想指定环境就加上--env dev之类的选项。返回码会反映测试用例是否全部通过这就为接入CI流程提供了天然的判断依据。5.2 一个最小可运行的 CI 示例假设团队想对每次代码提交都跑一遍核心接口冒烟测试可以把Bruno集合放在项目仓库的apis目录下然后在GitHub Actions或GitLab CI里加一步执行。用GitHub Actions举例步骤大致是jobs: api-test: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 - name: Install Bruno CLI run: npm install -g usebruno/cli - name: Run API tests run: bru run apis --env dev --output results.json - name: Upload test report uses: actions/upload-artifactv4 with: name: api-test-results path: results.json这个配置的用意在于接口测试和代码同仓库MR触发CI测试失败就拦住合入。对于接口变更频繁的后端项目这种做法能把接口回归成本压到很低。我在实际项目中把这套流程跑起来之后最明显的变化是需求提测阶段减少了很多“接口都通了吗”的返工沟通。5.3 内建了环境区分与报告输出CLI能走通关键是有环境变量和报告输出这两块支撑。--env参数可以指定用哪个环境变量文件所以同一个集合可以在本地跑dev环境、在流水线跑test环境不需要改请求内容。--output可以把测试结果导出为JSON或JUnit格式JUnit格式可以直接被很多CI平台的测试报告插件识别在流水线上生成可视化的测试趋势图。如果你已经很熟悉Postman的Newman会发现思路是类似的但体验上有一点不同Newman需要额外安装Node环境和Newman包而Bruno的CLI本身就是一个npm包体积比Newman轻盈和仓库的集成也比较自然。在Node环境下执行npm i -g usebruno/cli就可以用几乎不用折腾环境依赖。5.4 推荐哪种团队切过来基于我自己的使用体会Bruno特别适合这几类团队一是后端接口数量多、接口变更频繁需要把接口定义纳入版本管理和Code Review的团队二是接口涉及内网或敏感数据不希望请求信息落到第三方云上的团队三是已经跑代码流水线想把接口冒烟测试加进CI的团队。反过来如果你的团队极度依赖Postman的云端工作区习惯用Postman的共享链接让前端、测试、后端协作或者重度使用Postman的Mock Server、API网络公开接口等功能那么迁到Bruno会存在明显的功能落差。Bruno目前没有云端的Mock Server方案也没有Postman那样完整的API发布与共享社区它更像一个“在本地把接口调试做到极致”的工具。选不选它关键看你对“云端协作”和“本地优先Git协作”哪一套更认可。6. 用下来的几点真实体感与容易踩的坑6.1 启动虽快功能边界要心里有数先说结论Bruno在日常接口调试这个主航道上非常能打但它不是Postman的100%复刻品。它的本地优先设计带来的是速度和透明同时放弃了一部分“云”的能力。没有云同步意味着你换了电脑后需要从Git仓库拉取集合文件没有Mock Server意味着后端未就绪时需要自己搭一个简单的mock服务或用其他工具替代没有公开API网络的社区库意味着遇到“不知道某个API怎么调”的时候少了Postman社区的现成示例。这些边界我在用之前就看清楚了所以没有产生心理落差。对我而言接口调试工具最重要的能力就是“发请求、看响应、写断言”这三件事。这三件Bruno都做得足够好而且做到极致的轻。至于那些围绕Postman生态的高级云能力属于“附加题”有更好没有也不影响我把活干完。6.2 实测中踩过的几个具体坑第一个坑是环境变量的值只在请求发送时替换改完环境变量后已经在编辑区打开的URL串不会跟着实时刷新。我一开始改完baseUrl后回看URL发现还是旧地址愣了一下后来才发现要重新进入请求或者触发一次重渲染才会更新。这个不影响请求正确性但容易让人误解为“环境变量没生效”。第二个坑是导入Postman集合时Postman的预请求脚本和测试脚本不会自动翻译成Bruno脚本语法。Postman的脚本基于pm对象而Bruno用的是自己的一套JS接口。导入后测试脚本基本都是红色的报错状态需要人工重写。这里建议导入后重点检查带脚本的请求纯请求配置可以不用管。第三个坑是Cookie没有自动管理能力。Postman现在有内置的Cookie Jar会自动缓存响应里的Set-Cookie并在后续请求中带上。Bruno目前没有这么智能你需要手动从响应里把Cookie值拿出来写进Header或环境变量。对Cookie依赖很重的登录态接口这确实多了一步操作。比如登录之后服务端返回session_idxxxx后续请求需要手动把这个值放到Header的Cookie: session_idxxxx里。第四个坑是网络代理的设置。如果在公司内网需要通过代理访问外部接口Bruno的代理配置在设置里刚上手的人可能找不到。设置里配置好HTTP代理后请求会走代理。但它不像Postman那样直接复用系统代理需要显式填代理地址和端口。在需要反复切换代理和直连的场景下略有点繁琐。第五个坑和文件组织相关.bru文件使用中文文件名没有问题但要注意文件名重复的问题。同一个集合目录下不同子目录里的请求重名还好如果同一个目录下有两个同名.bru文件Bruno在展示时会出现歧义。建议从一开始就给每个请求起清晰且唯一的名称否则后期在命令行运行集合时会因为名称重复而难以定位。6.3 什么场景我会继续用它、什么场景我会回到 Postman经过一段时间的并行使用我的结论是个人日常调试和团队内网接口测试我会一直用Bruno和外部团队共享接口、公开API调研、需要在线Mock的时候我保留一个Postman作为备用。这个组合对我目前的工作流来说是效率最高的。Bruno最打动我的其实不是“快”这个字本身而是它把一个API客户端还原成了“工具”该有的样子体积小、启动快、不绑架账号、数据和项目同源。在一个接口调试工具身上这些本该就是默认能力只是过去几年大家被重量级工具教育惯了反而觉得能忍受那些毛病。我很乐意看到有产品愿意做减法也真心建议还没有试过的人花五分钟体验一次。反正下载也就10MB启动不到1秒试错成本几乎为零。你大概率会和我一样在某个平凡的下午试了它一下然后就回不去了。
返回列表