
1. 从“点发送”到“玩转流程”为什么你需要Postman脚本如果你用过Postman大概率还停留在“填个URL选个方法点下Send看看返回结果”的阶段。这没错Postman作为API测试工具入门门槛确实低。但如果你止步于此那可能只发挥了它10%的威力。我见过太多开发者和测试同学日复一日手动构造请求、复制粘贴Token、对比响应数据效率低下还容易出错。真正的效率提升始于自动化。而Postman脚本就是开启这扇大门的钥匙。它不是什么高深莫测的编程语言而是基于JavaScript内置于Postman的一套工具集。简单来说它允许你在发送请求“前”Pre-request Script和收到响应“后”Tests Script这两个关键节点插入自定义的逻辑。这就像给你的API请求装上了“大脑”和“质检员”。举个例子你测试一个需要登录态的接口。没有脚本时你得先手动调用登录接口从响应里复制出access_token再粘贴到下一个请求的Header里。有了脚本你可以写一个Pre-request Script让它自动从环境变量或上一个请求的响应中获取token并动态设置到当前请求的Header中。整个过程无声无息一键完成。再比如Tests Script可以自动断言响应状态码是否为200、响应体是否包含某个关键字段、甚至将响应中的某些数据保存下来供后续请求使用。所以学习Postman脚本语法不是为了炫技而是为了把你从重复、机械的劳动中解放出来构建可重复、可验证、智能化的API工作流。无论是单个接口的复杂校验还是多个接口串联的场景测试Collection Runner脚本都是不可或缺的核心能力。接下来我们就抛开那些枯燥的语法手册从实际应用场景出发手把手拆解Postman脚本的核心语法和实战技巧。2. 脚本的双生舞台Pre-request与Tests详解理解Postman脚本首先要搞清楚它运行的两个舞台Pre-request Script请求前脚本和Tests Script测试脚本。它们虽然都使用JavaScript但执行时机和核心使命截然不同用错了地方事倍功半。2.1 Pre-request Script请求的“装配工”顾名思义Pre-request Script在Postman发送HTTP请求之前执行。它的核心任务是为即将发出的请求“做准备”和“做加工”。你可以把它想象成生产线上的装配工在请求“出厂”前按照你的指令给它装上必要的“零件”。它的典型应用场景包括动态生成请求参数比如接口要求一个按时间戳生成的签名或者一个随机的订单号。// 生成一个当前时间戳秒级 const timestamp Math.floor(Date.now() / 1000); // 将生成的时间戳设置为一个环境变量供请求参数使用 pm.environment.set(current_timestamp, timestamp.toString()); // 生成一个随机字符串作为订单号 const randomOrderId TEST_${Math.random().toString(36).substr(2, 9)}; pm.environment.set(random_order_id, randomOrderId);自动化处理认证信息这是最常用的场景。从环境变量中读取Token并自动设置到请求头中。// 从环境变量获取access_token const accessToken pm.environment.get(access_token); // 如果token存在则设置Authorization头 if (accessToken) { pm.request.headers.add({ key: Authorization, value: Bearer ${accessToken} }); // 注意更常见的做法是直接更新或添加头确保唯一性 }注意pm.request.headers.add可能会添加重复的Header。更稳健的做法是使用pm.request.headers.upsert({key: Authorization, value:Bearer ${accessToken}})它会更新已存在的头或新增。条件性构建请求根据某些条件如环境变量值决定请求的URL、方法或Body。const env pm.environment.get(env); let baseUrl; if (env production) { baseUrl https://api.yourcompany.com; } else { baseUrl https://api-staging.yourcompany.com; } // 假设原始请求URL是 /v1/user这里可以动态拼接 pm.request.url new URL(pm.request.url.toString().replace({{base_url}}, baseUrl));核心要点Pre-request Script 操作的对象是pm.request你可以修改它的URL、Headers、Body等属性。它执行时请求还未发出。2.2 Tests Script响应的“质检员”Tests Script 在Postman收到HTTP响应之后执行。它的核心任务是对收到的响应进行“检验”和“数据提取”。就像质检员检查产品响应是否符合标准断言并把有用的信息如token、ID分门别类放好存储变量。它的典型应用场景包括自动化断言测试这是“Tests”名字的由来。验证状态码、响应时间、响应体结构及内容。// 检查状态码是否为200 pm.test(Status code is 200, function () { pm.response.to.have.status(200); }); // 检查响应时间小于500ms pm.test(Response time is less than 500ms, function () { pm.expect(pm.response.responseTime).to.be.below(500); }); // 检查JSON响应体中包含特定字段且值正确 pm.test(Response body has correct user name, function () { const responseJson pm.response.json(); pm.expect(responseJson.data.user.name).to.eql(John Doe); }); // 检查响应体包含某个字符串 pm.test(Body contains success message, function () { pm.expect(pm.response.text()).to.include(success); });提取并存储响应数据将响应中的关键数据保存到环境变量或全局变量中供后续请求使用。这是实现接口串联的关键。// 解析JSON响应 const responseJson pm.response.json(); // 假设登录接口返回 {“token”: “abc123”, “user_id”: 456} if (responseJson.token) { // 将token存储到环境变量 pm.environment.set(access_token, responseJson.token); console.log(Access token saved:, responseJson.token); } if (responseJson.user_id) { pm.environment.set(current_user_id, responseJson.user_id.toString()); }设置请求为通过/失败基于复杂的断言逻辑手动控制本次请求在Test Results中的显示状态。const responseJson pm.response.json(); if (responseJson.code 0 responseJson.data) { // 业务逻辑成功标记测试通过 pm.test(Business logic passed, function () { /* ... */ }); } else { // 业务逻辑失败可以抛出一个错误使测试失败 pm.test(“Business logic failed with code: ” responseJson.code, function () { pm.expect.fail(“Business error: ” responseJson.msg); }); }核心要点Tests Script 操作的对象是pm.response和pm环境/全局变量API。它执行时请求已经完成响应数据已就绪。两者关系与工作流一个完整的自动化测试用例往往是两者配合。Pre-request负责“备料”如加Token请求发出后Tests负责“验货”断言状态和业务数据和“备下一份料”提取数据存为变量。在Collection Runner中这个流程会按顺序在多个请求间循环形成自动化工作流。3. pm对象你的脚本“瑞士军刀”无论是Pre-request还是Tests脚本你的主要操作对象都是一个名为pm的全局对象。它是Postman专门为脚本环境注入的“瑞士军刀”提供了所有你需要的能力。理解pm的核心子对象和方法是写好脚本的关键。3.1 pm.environment 与 pm.globals变量的舞台变量是Postman脚本的血液用于在不同请求和脚本间传递数据。pm.environment和pm.globals是管理两类不同作用域变量的对象。pm.environment操作环境变量。环境变量与特定的“环境”Environment绑定比如“开发环境”、“测试环境”、“生产环境”。你可以快速切换环境来改变变量值非常适合管理不同环境的配置如base_url, app_key。// 获取环境变量 const baseUrl pm.environment.get(base_url); const apiKey pm.environment.get(api_key); // 设置环境变量 pm.environment.set(access_token, new_token_value_here); pm.environment.set(request_id, Date.now().toString()); // 取消设置删除环境变量 pm.environment.unset(temp_variable);pm.globals操作全局变量。全局变量在所有环境中都有效作用域最大。通常用于存储一些真正全局的、与环境无关的数据但使用需谨慎避免命名冲突。// 设置一个全局计数器 let count pm.globals.get(execution_count) || 0; count; pm.globals.set(execution_count, count);选择策略优先使用环境变量。将配置信息URL密钥放在环境变量中将运行时产生的临时数据token 上次响应的ID也放在环境变量里。全局变量仅用于极少数跨所有环境的共享状态。3.2 pm.request 与 pm.response请求与响应的本体这两个对象提供了对当前请求和响应的完全访问能力。pm.request主要在Pre-request Script中使用。你可以读取和修改即将发出的请求的详细信息。// 读取请求方法、URL console.log(“Request Method:”, pm.request.method); console.log(“Request URL:”, pm.request.url.toString()); // 修改请求头在Pre-request中 // 添加或更新一个Header pm.request.headers.upsert({key: ‘X-Custom-Header’, value: ‘MyValue’}); // 获取所有头进行遍历或查找 const headers pm.request.headers; headers.each(header { if (header.key ‘Content-Type’) { console.log(‘Found Content-Type:’, header.value); } }); // 修改请求体对于非二进制Body if (pm.request.body pm.request.body.mode ‘raw’) { const rawBody pm.request.body.toString(); try { const jsonBody JSON.parse(rawBody); jsonBody.timestamp new Date().toISOString(); // 动态添加字段 pm.request.body JSON.stringify(jsonBody, null, 2); } catch (e) { console.log(‘Body is not JSON, skipping modification’); } }pm.response主要在Tests Script中使用。用于访问和分析收到的响应。// 基本响应信息 console.log(“Status Code:”, pm.response.code); console.log(“Status Text:”, pm.response.status); console.log(“Response Time:”, pm.response.responseTime ‘ms’); console.log(“Response Size:”, pm.response.responseSize ‘ bytes’); // 响应头 const contentType pm.response.headers.get(“Content-Type”); console.log(“Content-Type:”, contentType); // 响应体 - 文本形式 const responseText pm.response.text(); console.log(“Response Text (first 500 chars):”, responseText.substr(0, 500)); // 响应体 - JSON形式如果Content-Type是application/json // 这是最常用的方式 try { const jsonData pm.response.json(); console.log(“Parsed JSON data:”, jsonData); // 现在可以方便地访问 jsonData.property } catch (e) { console.log(“Response is not valid JSON or is empty.”); } // 响应体 - 其他形式如XML 需要额外解析3.3 pm.test 与 pm.expect断言的核心pm.test和pm.expect是编写测试断言的主要工具它们构成了一个行为驱动开发BDD风格的断言库语法清晰易读。pm.test(name, fn)定义一个测试用例。name是显示在测试结果面板中的描述fn是包含断言逻辑的函数。pm.expect(actual)启动一个断言链针对actual实际值进行断言。它们通常结合使用pm.test(“Test case: Check status and data”, function () { // 断言1状态码为200 pm.expect(pm.response.code).to.equal(200); // 断言2响应包含特定头 pm.expect(pm.response.headers.get(‘Content-Type’)).to.include(‘application/json’); // 断言3JSON响应体的某个字段存在且为特定值 const jsonData pm.response.json(); pm.expect(jsonData).to.have.property(‘success’, true); pm.expect(jsonData.data).to.be.an(‘array’).that.is.not.empty; pm.expect(jsonData.data[0].id).to.be.a(‘number’).above(0); }); // 你也可以单独使用pm.expect进行断言但不会在测试结果中生成独立的条目 if (pm.response.code ! 200) { console.error(“Unexpected status code:”, pm.response.code); }丰富的断言链pm.expect提供了丰富的链式方法如.to.equal/ .to.eql(深度相等)、.to.include、.to.have.property、.to.be.a/an(类型判断)、.to.be.above/below(数字比较)、.to.match(正则匹配) 等几乎能满足所有验证需求。3.4 其他实用pm APIpm.variables一个通用的变量获取接口它会按局部变量 - 数据变量 - 环境变量 - 全局变量的顺序查找并返回第一个找到的值。在不确定变量存储位置时使用很方便。const token pm.variables.get(“access_token”); // 自动查找pm.visualizer允许你使用HTML和JavaScript将响应数据渲染成自定义的可视化图表对于展示复杂数据非常有用。pm.info提供关于当前脚本执行环境的信息如迭代次数、请求名称等在Collection Runner中调试时很有帮助。console.log(“Current request name:”, pm.info.requestName); console.log(“Iteration:”, pm.info.iteration 1, “of”, pm.info.iterationCount);掌握pm对象你就掌握了Postman脚本编程的绝大部分能力。接下来的问题就是如何用这些能力解决具体问题了。4. 实战演练构建一个完整的自动化登录-查询流程光说不练假把式。让我们设计一个经典的实战场景自动化测试一个用户系统。流程是1. 用户登录 - 2. 获取用户信息 - 3. 更新用户资料。我们将用Collection组织这三个请求并用脚本将它们串联起来。4.1 第一步登录接口脚本编写首先创建一个名为用户登录的POST请求URL是{{base_url}}/auth/loginBody发送JSON{“username”: “{{test_user}}”, “password”: “{{test_pwd}}”}。这里base_url,test_user,test_pwd都是预先在环境变量中设置好的。这个请求的Tests Script是关键我们需要提取登录成功后返回的token。// 1. 基础断言确保登录请求本身成功 pm.test(“Login request succeeded”, function () { pm.response.to.have.status(200); pm.expect(pm.response.responseTime).to.be.below(1000); // 响应时间应小于1秒 }); // 2. 解析响应并断言业务逻辑 const responseJson pm.response.json(); pm.test(“Login business logic is correct”, function () { // 假设成功返回格式为 {“code”: 0, “message”: “success”, “data”: {“token”: “xxx”}} pm.expect(responseJson.code).to.equal(0); pm.expect(responseJson.message).to.include(“success”); pm.expect(responseJson.data).to.be.an(‘object’); pm.expect(responseJson.data).to.have.property(‘token’); }); // 3. 提取并存储关键数据 if (responseJson.code 0 responseJson.data.token) { const accessToken responseJson.data.token; // 将token存储到环境变量供后续请求使用 pm.environment.set(“access_token”, accessToken); console.log(“Access token saved to environment:”, accessToken); // 假设响应里还有用户ID也存下来 if (responseJson.data.user_id) { pm.environment.set(“current_user_id”, responseJson.data.user_id.toString()); } } else { // 如果登录失败清除可能存在的旧token避免后续请求使用错误凭证 pm.environment.unset(“access_token”); console.error(“Login failed, cleared access_token.”); // 可以强制让测试失败 pm.test(“Login failed, check credentials or API”, function () { pm.expect.fail(“Login response indicates failure: ” JSON.stringify(responseJson)); }); }4.2 第二步获取用户信息接口脚本编写创建第二个请求获取用户信息方法是GETURL是{{base_url}}/user/{{current_user_id}}。这个请求需要携带上一步获取的Token。我们在这个请求的Pre-request Script中自动添加认证头// 从环境变量获取token const token pm.environment.get(“access_token”); // 检查token是否存在如果不存在可能意味着上一步登录失败可以给出警告或跳过 if (!token) { console.warn(“Access token is missing! The request may fail due to unauthorized.”); // 可以选择性地在这里抛出一个错误停止请求发送 // throw new Error(“Access token is required for this request.”); } // 使用upsert确保Authorization头被正确设置更新或添加 pm.request.headers.upsert({ key: ‘Authorization’, value: Bearer ${token} }); console.log(“Authorization header set with token.”);在它的Tests Script中我们验证用户信息是否正确返回并可能提取更多数据pm.test(“Status is 200 OK”, () pm.response.to.have.status(200)); const userInfo pm.response.json(); pm.test(“Response contains user profile”, function () { pm.expect(userInfo.data).to.be.an(‘object’); pm.expect(userInfo.data).to.have.property(‘username’); pm.expect(userInfo.data.username).to.eql(pm.environment.get(“test_user”)); // 验证用户名匹配登录用户 // 存储邮箱可能用于下一步更新 if (userInfo.data.email) { pm.environment.set(“user_email”, userInfo.data.email); } });4.3 第三步更新用户资料接口脚本编写创建第三个请求更新用户资料方法是PUTURL是{{base_url}}/user/profile。同样需要在Pre-request Script中设置Authorization头脚本与第二步几乎相同可复用。它的请求Body需要动态构造比如我们想更新用户的邮箱。我们可以在Pre-request Script中动态修改Body// 1. 设置认证头同上 const token pm.environment.get(“access_token”); pm.request.headers.upsert({key: ‘Authorization’, value: Bearer ${token}}); // 2. 动态构建或修改请求体 // 假设原始请求Body是一个JSON {“email”: “”} // 我们将其读取、修改、再写回 if (pm.request.body pm.request.body.mode ‘raw’) { try { const bodyData JSON.parse(pm.request.body.toString()); // 生成一个新的测试邮箱例如在原邮箱基础上加时间戳 const originalEmail pm.environment.get(“user_email”) || “testexample.com”; const newEmail originalEmail.replace(‘’, ${Date.now()}); // 生成唯一邮箱 bodyData.email newEmail; // 将修改后的对象设置回请求体 pm.request.body JSON.stringify(bodyData, null, 2); console.log(“Updated request body with new email:”, newEmail); // 也可以将新邮箱存下来供后续断言使用 pm.environment.set(“updated_email”, newEmail); } catch (e) { console.error(“Failed to parse or modify request body:”, e.message); } }在Tests Script中验证更新是否成功pm.test(“Update profile succeeded”, function () { pm.response.to.have.status(200); // 或204等成功状态码 const responseJson pm.response.json(); pm.expect(responseJson.code).to.equal(0); }); // 可选立即调用一次获取用户信息验证邮箱是否已更新 // 但这通常会在下一个测试用例或手动验证中完成4.4 使用Collection Runner串联执行将这三个请求保存到一个Collection中比如命名为“用户流程测试”。然后打开Collection Runner。选择环境在Runner界面选择包含base_url,test_user,test_pwd的环境。设置迭代可以设置迭代次数进行压力测试或数据驱动测试。数据文件高级你可以上传一个JSON或CSV文件文件中的每一行数据会作为一次迭代的输入替换请求中的变量如{{test_user}}实现数据驱动测试。点击运行Collection Runner会按顺序执行这三个请求。你会看到第一个登录请求成功后Tests脚本将token存入环境变量。第二个请求的Pre-request脚本自动取出token并添加到请求头然后发送。第三个请求同理并且动态修改了请求体。所有Tests脚本的断言结果都会在运行结束后汇总显示。通过这个流程你实现了一个完全自动化的、端到端的API场景测试。无需手动复制粘贴任何数据。5. 高阶技巧与避坑指南掌握了基础流程后一些高阶技巧和常见“坑点”能让你更游刃有余。5.1 动态变量与Mock数据生成Postman提供了动态变量Dynamic Variables可以在脚本中通过{{$variableName}}引用但更强大的方式是在脚本中直接用JavaScript生成。// 1. 使用Postman内置的动态变量在请求URL或Body中直接写 {{$guid}} 等 // 在脚本中获取动态变量值比较麻烦通常直接用于请求构造。 // 2. 使用JavaScript生成更灵活的Mock数据 // 随机整数 const randomInt Math.floor(Math.random() * 10000); // 随机字符串 const randomString Math.random().toString(36).substring(2, 15); // 当前时间戳 (ISO格式) const isoTimestamp new Date().toISOString(); // 当前时间戳 (秒) const timestampSec Math.floor(Date.now() / 1000); // 随机手机号示例 const randomMobile 1${Math.floor(Math.random() * 9000000000) 1000000000}; // 将这些数据设置到变量中或直接用于请求体 pm.environment.set(“order_number”, ORDER_${timestampSec}_${randomInt});5.2 脚本的模块化与复用全局脚本与文件夹脚本当脚本变得复杂时避免重复代码。Collection级别的脚本在Collection的Pre-request Scripts和Tests标签页中编写的脚本会对Collection下的所有请求生效。这非常适合放置一些通用逻辑比如统一的请求头设置、通用的响应时间断言等。执行顺序是Collection Pre-request - Folder/Request Pre-request - 发送请求 - Collection Tests - Folder/Request Tests。Folder级别的脚本在Folder层级也可以添加脚本对该文件夹下的所有请求生效。优先级高于Collection低于单个请求。单个请求的脚本优先级最高会覆盖上层定义的相同逻辑。最佳实践将通用的认证逻辑、日志记录放在Collection级Pre-request脚本中将业务通用的断言如响应格式标准放在Collection级Tests脚本中将具体的业务逻辑放在各自请求的脚本中。5.3 常见“坑点”与调试技巧变量未定义或值为null这是最常见的问题。在脚本中使用pm.environment.get(“var_name”)前务必确认该变量已在你选择的环境中正确设置。使用||操作符提供默认值是个好习惯。const token pm.environment.get(“access_token”) || “”; // 避免undefined if (!token) { console.warn(“Token is empty!”); }脚本执行顺序误解牢记Pre-request和Tests的执行时机。不要在Tests里试图修改当前请求的pm.request它已经发出去了也不要在Pre-request里访问pm.response它还没回来。异步操作问题Postman脚本环境是同步的。你不能使用setTimeout,Promise,async/await等异步操作来控制脚本执行流程或等待。所有代码都是顺序执行完毕后才发送请求或完成测试。JSON解析错误在Tests中pm.response.json()时如果响应体不是合法的JSON或为空会抛出异常导致后续脚本停止。务必用try...catch包裹。let jsonData; try { jsonData pm.response.json(); } catch (e) { console.error(“Failed to parse response as JSON:”, pm.response.text()); jsonData {}; // 赋予默认值 // 或者标记测试失败 pm.test(“Response is valid JSON”, function () { pm.expect.fail(“Invalid JSON response”); }); } // 安全地使用 jsonData if (jsonData jsonData.code) { /* ... */ }使用Console调试Postman内置的Console(View - Show Postman Console 或 CtrlAltC) 是调试脚本的神器。所有console.log(),console.warn(),console.error()的输出以及网络请求的详细信息都会在这里显示。遇到问题时打开Console查看日志是第一步。环境切换导致变量丢失在Collection Runner中运行后脚本修改的环境变量是临时的仅在该次运行会话中有效。关闭Runner或切换环境后这些临时值会消失。持久化修改需要通过pm.environment.set写入到具体的环境文件中需要你有该环境的编辑权限。6. 从脚本到工作流Newman与持续集成当你本地用Collection Runner跑通了一套复杂的API测试流程后下一步自然是想把它集成到团队的持续集成/持续部署CI/CD流水线中实现每次代码提交或部署时的自动化测试。这就是Newman的用武之地。Newman是Postman的命令行集合运行器让你能够在终端、脚本或CI服务器如Jenkins, GitLab CI, GitHub Actions中运行Postman Collection。基本使用步骤导出Collection和环境变量在Postman中将你的Collection包含所有请求和脚本导出为JSON文件如my_api_tests.postman_collection.json。同样将测试所需的环境也导出为JSON文件如staging_env.postman_environment.json。安装Newman确保你已安装Node.js然后通过npm全局安装Newman。npm install -g newman运行测试在命令行中执行。newman run my_api_tests.postman_collection.json \ -e staging_env.postman_environment.json \ --reporters cli,html,json \ --reporter-html-export newman_report.html \ --reporter-json-export newman_report.jsonrun: 指定要运行的Collection文件。-e: 指定环境变量文件。--reporters: 指定报告生成器cli在终端输出html生成美观的HTML报告json生成机器可读的JSON报告。--reporter-*-export: 指定报告输出路径。集成到CI/CD以GitHub Actions为例你可以在仓库中创建.github/workflows/api-tests.yml文件name: API Tests on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkoutv3 - name: Setup Node.js uses: actions/setup-nodev3 with: { node-version: ‘18’ } - name: Install Newman run: npm install -g newman - name: Run API Tests run: | newman run ./postman/collections/my_api_tests.json \ -e ./postman/environments/staging.json \ --reporters cli,html \ --reporter-html-export ./newman-report.html - name: Upload HTML Report uses: actions/upload-artifactv3 with: name: newman-html-report path: ./newman-report.html这样每次代码推送或PR时都会自动运行你的Postman API测试集并生成可下载的测试报告。给脚本加上“CI友好”的考量避免交互依赖CI环境是无界面的确保你的脚本不依赖任何手动操作或弹窗。清晰的测试输出在Tests脚本中使用pm.test给出明确的测试描述这样在CI日志和报告中才能清晰看到通过/失败的项目。处理外部依赖如果你的测试依赖数据库特定状态或第三方服务考虑在Collection的最前面添加“初始化”请求或在CI流水线中添加准备步骤。退出码Newman会根据测试结果返回不同的退出码0表示全部通过非0表示有失败。CI系统可以根据退出码判断构建状态。从在Postman GUI里写几行脚本到通过Newman在CI流水线中自动运行成千上万个API测试你构建的不仅仅是一套测试用例更是一个可靠、可重复的API质量保障体系。脚本语法是起点自动化工作流和持续集成才是其价值的最终体现。