尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Postman预请求脚本:从手动调试到自动化接口测试的进阶指南

Postman预请求脚本:从手动调试到自动化接口测试的进阶指南 1. 项目概述从“点发送”到“智能请求”如果你还在用Postman手动填参数、复制粘贴Token那你的效率至少被浪费了50%。Postman远不止一个“高级版的浏览器地址栏”它的核心威力在于自动化。而预请求脚本正是开启这扇自动化大门的钥匙。简单来说预请求脚本就是在你的HTTP请求真正被发送出去之前由Postman自动执行的一段JavaScript代码。这听起来可能有点抽象我举个例子你需要测试一个需要登录态的接口常规操作是先手动调用登录接口从返回的JSON里把token字段复制出来再粘贴到下一个请求的Authorization头里。一天测十个接口这个动作就要重复十次枯燥且易错。而预请求脚本能让你在点击“Send”的瞬间自动完成登录、提取Token、并设置到请求头里这一系列操作。你的操作从“复制粘贴”变成了“一键发送”这就是质的飞跃。它解决的不仅仅是“懒”的问题更是一致性、可靠性和复杂场景模拟的问题。比如你需要为每个请求自动生成一个时间戳签名或者动态计算一个HMAC加密的请求头又或者需要从上一个请求的响应里取出一个ID作为本次请求的路径参数。这些靠人手几乎无法保证每次都不出错但交给脚本就是100%的准确。这篇文章我会以一个拥有多年接口调试和自动化测试经验的开发者视角带你彻底吃透Postman的预请求脚本。我不会只告诉你“怎么写”我会重点拆解“为什么这么写”以及在实际项目中那些官方文档里不会写的“坑”和“骚操作”。无论你是刚接触接口测试的新手还是想提升团队协作效率的老鸟相信都能找到你需要的东西。2. 预请求脚本的核心能力与设计思路2.1 它能做什么不只是设置变量很多人对预请求脚本的理解停留在“设置个环境变量”这实在是太小看它了。基于Node.js和沙箱环境的Postman运行时赋予了脚本非常强大的能力。我们可以从以下几个维度来理解它的作用域操控本次请求的一切这是最基本也是最核心的能力。你可以在脚本里动态修改即将发出的请求的任何一个部分。URL与参数动态拼接URL路径、修改或添加查询参数Query Params。请求头Headers添加、删除或修改请求头比如自动生成Authorization、Content-Type、Timestamp、Sign等。请求体Body无论是form-data、x-www-form-urlencoded还是raw如JSON你都可以在发送前动态构建或修改其内容。例如将一个JSON对象序列化后赋值给请求体。请求方法理论上你也可以改但通常不这么做。访问与操作变量系统Postman的变量系统是它的中枢神经。预请求脚本可以自由地设置变量pm.variables.set(“key”, “value”)这是最常用的。获取变量pm.variables.get(“key”)或使用模板语法{{key}}在字符串中。操作范围包括环境变量、集合变量、全局变量和局部变量。理解它们的优先级和作用域是关键。引入外部逻辑与复杂计算加密签名这是高频刚需。比如你需要对请求参数按特定规则排序后进行MD5、SHA256或HMAC-SHA1签名。脚本可以引入Postman内置的CryptoJS库或forge库轻松完成。生成测试数据动态生成随机用户名、手机号、邮箱或者一个符合特定格式的字符串。流程控制结合setNextRequest函数你可以在集合运行器中实现简单的接口调用流程控制比如“只有登录成功后才执行查询接口”。发起额外请求谨慎使用通过pm.sendRequest你可以在预请求脚本中先发起一个请求比如获取一个临时的access_token然后再用这个token去执行主请求。这实现了请求的链式调用。但要注意这会增加单次请求的耗时且要处理好异步回调。注意预请求脚本的执行是同步阻塞的。也就是说脚本里的所有代码包括pm.sendRequest的异步回调都必须执行完毕后主请求才会被发出。设计脚本时要避免死循环或耗时极长的操作。2.2 设计思路何时用怎么规划不是每个请求都需要预请求脚本。滥用它会增加维护成本。我的经验是在以下场景考虑使用认证与签名这是头号应用场景。所有需要Token、签名、加密的接口都必须用预请求脚本自动化。参数依赖当前请求的参数值依赖于其他变量、复杂计算或前序请求的响应。数据准备与清理在请求前生成或准备特定的测试数据或者在请求后清理测试数据这属于测试脚本范畴但思路相通。条件逻辑需要根据某些条件如环境变量、时间等决定本次请求的URL、参数或是否跳过。在设计脚本时我遵循一个原则高内聚低耦合。对于单个接口的独特逻辑比如某个特定接口的加密算法脚本直接写在该请求的“Pre-request Script”标签页里。对于集合Collection级别的通用逻辑比如整个项目统一的Token获取和刷新机制则写在集合的预请求脚本中。集合下的所有请求在执行时都会先运行这段脚本。这是实现自动化测试套件的基石。避免在脚本里写死Hardcode任何可能变化的值。所有配置化的东西如服务器地址、AppKey、Secret等都应该放在环境变量或集合变量中。这样一套脚本就能通过切换环境来测试开发、测试、生产等不同服务。3. 从零开始你的第一个预请求脚本让我们从一个最简单的例子开始感受一下脚本是如何工作的。假设我们有一个获取用户信息的接口GET /api/user/{{userId}}我们需要在请求前自动将userId设置为一个随机数。3.1 基础环境与界面首先确保你有一个打开的Postman任何版本免费版即可。创建一个新的请求方法设为GETURL暂时留空。然后看向请求编辑区的右侧你会看到一排标签页“Params”“Authorization”“Headers”“Body”... 继续往右看找到“Pre-request Script”标签页点击它。这就是你编写脚本的主战场。界面下方是一个代码编辑器支持JavaScript语法高亮和基本的自动补全。旁边还有一个“Snippets”区域提供了一些常用代码片段对于初学者非常友好。3.2 编写并理解第一个脚本我们的目标是生成一个1到1000之间的随机整数并将其设置为userId变量然后在URL中使用它。在“Pre-request Script”编辑器中输入以下代码// 生成一个1到1000之间的随机整数 const randomUserId Math.floor(Math.random() * 1000) 1; console.log(“生成的用户ID”, randomUserId); // 将生成的ID设置到一个变量中这里我们设置为局部变量 pm.variables.set(“userId”, randomUserId);现在回到“URL”输入框输入https://your-api-server.com/api/user/{{userId}}。注意我们用双花括号{{}}引用了刚才脚本中设置的变量。点击“Send”。神奇的事情发生了。在发送请求之前Postman执行了我们的脚本生成了一个随机数并将其赋给了变量userId。然后在构建实际请求URL时{{userId}}被替换成了那个随机数。你可以在Postman底部的“Console”视图 - 显示Postman控制台里看到我们打印的日志。我们来拆解一下这段代码Math.random()生成一个[0, 1)的随机小数。乘以1000得到[0, 1000)的随机数。Math.floor()向下取整得到0-999的整数。1将其变为1-1000的整数。pm.variables.set(“userId”, randomUserId)是Postman提供的API用于设置变量。这里将值设置为了局部变量仅作用于当前请求。console.log用于调试输出信息到控制台在编写复杂脚本时非常有用。3.3 变量作用域详解与选择上例中我们使用了pm.variables.set它默认设置的是局部变量。理解Postman的变量作用域至关重要这直接关系到你脚本的健壮性和可维护性。Postman的变量主要有四个作用域优先级从高到低依次为局部变量Local仅作用于单个请求。在脚本中通过pm.variables.set设置或通过{{}}在请求中定义。请求执行完毕后即销毁。适用于临时性、一次性的数据。数据变量Data在使用Collection Runner或Newman运行数据文件CSV/JSON时引入用于数据驱动测试。环境变量Environment作用于选定的某个环境如“开发环境”、“测试环境”。用于存储与环境相关的配置如base_url,api_key等。通过pm.environment.set和pm.environment.get操作。集合变量Collection作用于整个集合Collection。用于存储集合内所有请求共享的常量或配置。通过pm.collectionVariables.set和pm.collectionVariables.get操作。全局变量Global作用于整个Postman工作空间所有请求和集合都可访问。应谨慎使用避免污染。通过pm.globals.set和pm.globals.get操作。实操心得对于像userId这样的每次请求都可能变化的测试数据使用局部变量是合适的。但对于服务器地址base_url、应用密钥app_secret这类固定配置必须使用环境变量。这样做的好处是环境隔离一套脚本通过切换环境就能测试不同服务器。安全敏感信息不暴露在脚本代码中而是存储在环境配置里可以导出为不含敏感信息的配置文件进行共享。维护方便修改配置只需在环境管理中修改一处。修改上面的例子假设我们的基础URL是环境变量// 从环境变量中获取基础URL和固定的测试用户ID如果有的话 const baseUrl pm.environment.get(“base_url”); // 生成随机用户ID的逻辑不变 const randomUserId Math.floor(Math.random() * 1000) 1; pm.variables.set(“userId”, randomUserId); // 注意我们不在脚本里拼接完整的URL而是在URL栏使用模板语法 // URL 栏应填写{{base_url}}/api/user/{{userId}}这样当你从“开发环境”切换到“测试环境”时只需要在环境下拉框切换base_url会自动变化脚本无需任何修改。4. 实战进阶处理复杂认证与签名现在我们来处理一个更真实、也更复杂的场景为请求添加动态的HMAC-SHA256签名。这是很多开放API特别是支付、金融类接口的常见要求。4.1 场景还原与算法解析假设接口规范如下签名算法HMAC-SHA256签名源串将请求方法GET/POST、请求路径不含域名、以及所有查询参数Query String按参数名ASCII码升序排序后用连接成字符串。例如GET/api/v1/orderappid123timestamp1678886400签名计算使用app_secret作为密钥对上述源串进行HMAC-SHA256计算得到二进制摘要再转换为十六进制小写字符串。携带签名将计算出的签名放在请求头X-Signature中。我们的任务是在预请求脚本中自动完成这个签名过程。4.2 分步实现签名脚本首先确保你的环境变量里已经设置了appid和app_secret。在请求的“Pre-request Script”中我们一步步实现// 1. 获取必要的变量 const appId pm.environment.get(“appid”); const appSecret pm.environment.get(“app_secret”); const method request.method; // 获取当前请求方法 const url new URL(request.url); // 解析URL对象 const path url.pathname; // 获取路径如 /api/v1/order let timestamp Math.floor(Date.now() / 1000); // 生成当前10位时间戳 // 2. 构建待签名的参数字符串 let params { “appid”: appId, “timestamp”: timestamp }; // 将URL自带的查询参数也合并进来 url.searchParams.forEach((value, key) { params[key] value; }); // 3. 按参数名ASCII升序排序 const sortedKeys Object.keys(params).sort(); const sortedParamStr sortedKeys.map(key ${key}${params[key]}).join(‘’); // 4. 拼接最终的签名源串 const signString ${method}${path}${sortedParamStr}; console.log(‘待签名字符串’, signString); // 5. 计算HMAC-SHA256签名 // Postman内置了CryptoJS库 const hash CryptoJS.HmacSHA256(signString, appSecret); const signature hash.toString(CryptoJS.enc.Hex); // 转为十六进制字符串 console.log(‘计算出的签名’, signature); // 6. 将时间戳和签名设置到请求中 // 设置时间戳为局部变量方便在URL或Body中引用如果需要 pm.variables.set(“timestamp”, timestamp); // 直接设置请求头 pm.request.headers.add({ key: ‘X-Signature’, value: signature }); // 也可以将appid和timestamp添加到查询参数或请求头根据接口要求来 // 例如添加到查询参数 // pm.request.url.addQueryParams([{ key: ‘appid’, value: appId }, { key: ‘timestamp’, value: timestamp.toString() }]);关键点解析request对象在预请求脚本中request对象代表了即将发出的请求我们可以从中读取或修改它的属性如method,url,headers。URL接口这是Web标准的URL接口用于方便地解析和操作URL。url.searchParams是一个URLSearchParams对象便于处理查询参数。CryptoJSPostman沙箱环境内置的加密库无需require直接使用。支持MD5、SHA系列、HMAC、AES等常见算法。pm.request.headers.add动态添加请求头。如果头已存在此操作会添加一个新值。你也可以用pm.request.headers.upsert来更新已存在的头。4.3 封装与复用将签名逻辑抽象为集合级脚本如果集合里有几十个接口都需要同样的签名逻辑把上面这段代码复制粘贴到每个请求里是灾难性的。一旦签名规则变化你需要修改几十个地方。正确的做法是将通用签名逻辑放在集合的预请求脚本中。在侧边栏右键点击你的集合选择“Edit”。在弹出的窗口中切换到“Pre-request Scripts”标签页。将上面计算签名的核心逻辑从获取变量到计算签名封装成一个函数比如generateSignature(request, appId, appSecret)。在集合脚本中调用这个函数并为pm.request添加签名头。这样集合下的每一个请求在执行前都会先运行这段集合级脚本自动获得签名。对于某个不需要签名的特殊请求比如登录接口本身你可以在该请求的预请求脚本中使用pm.request.headers.remove(‘X-Signature’)来移除集合脚本添加的签名头或者用更优雅的条件判断。实操心得签名调试签名不对是调试API时最头疼的问题之一。99%的错误源于签名源串的拼接规则与服务器端不一致。务必使用console.log将每一步生成的字符串都打印出来特别是最终的signString。然后与服务器端在相同输入下生成的字符串进行逐字符比对包括大小写、空格、排序顺序、编码等。Postman控制台是你的最佳拍档。5. 高级技巧动态数据、链式请求与流程控制5.1 生成动态测试数据测试经常需要不重复的数据。我们可以利用JavaScript的Math.random()和Date.now()或者一些预定义的库来生成。// 生成随机手机号中国大陆 function generateMobile() { const prefixArray [“130”, “131”, “132”, “133”, “135”, “137”, “138”, “170”, “187”, “189”]; const prefix prefixArray[Math.floor(Math.random() * prefixArray.length)]; let suffix “”; for (let i 0; i 8; i) { suffix Math.floor(Math.random() * 10); } return prefix suffix; } // 生成随机邮箱 function generateEmail() { const domains [“example.com”, “test.com”, “demo.org”]; const domain domains[Math.floor(Math.random() * domains.length)]; const name Math.random().toString(36).substring(2, 10); // 随机字符串 return ${name}${domain}; } const randomMobile generateMobile(); const randomEmail generateEmail(); // 设置为变量可以在请求体或URL中使用 pm.variables.set(“random_mobile”, randomMobile); pm.variables.set(“random_email”, randomEmail); // 如果是JSON请求体可以直接构建并赋值 const requestBody { username: user_${Date.now()}, mobile: randomMobile, email: randomEmail, age: Math.floor(Math.random() * 50) 18 }; // 注意如果请求体格式是JSON需要将其序列化成字符串 pm.request.body.raw JSON.stringify(requestBody);注意直接操作pm.request.body.raw会覆盖你在“Body”标签页手动填写的内容。通常更推荐的方式是在“Body”标签页以模板形式编写JSON如{“mobile”: “{{random_mobile}}”}然后在脚本中只设置变量。5.2 使用pm.sendRequest实现链式调用这是预请求脚本中最强大的功能之一允许你在主请求前先执行另一个请求并根据其响应来设置主请求的参数。典型场景自动获取并刷新Token。// 定义一个获取Token的函数 function getAccessToken(callback) { const tokenRequest { url: pm.environment.get(“auth_url”), method: ‘POST’, header: { ‘Content-Type’: ‘application/json’ }, body: { mode: ‘raw’, raw: JSON.stringify({ grant_type: ‘client_credentials’, client_id: pm.environment.get(“client_id”), client_secret: pm.environment.get(“client_secret”) }) } }; pm.sendRequest(tokenRequest, function (err, response) { if (err) { console.error(‘获取Token失败’, err); // 这里可以决定是否继续执行主请求或者抛出错误 // 为了演示我们设置一个默认值或空值 pm.variables.set(“access_token”, “”); callback(); // 仍然调用回调避免主请求永远不发送 } else { const jsonData response.json(); const newToken jsonData.access_token; const expiresIn jsonData.expires_in; console.log(‘获取到新Token’, newToken, ‘过期时间’, expiresIn); // 将Token设置到环境变量中这样同一环境下的其他请求也能用 pm.environment.set(“access_token”, newToken); // 可以计算一个过期时间戳用于后续判断Token是否快过期了 const expireTime Date.now() (expiresIn * 1000) - 60000; // 提前1分钟过期 pm.environment.set(“token_expire_time”, expireTime); callback(); // Token获取成功执行回调 } }); } // 主逻辑检查现有Token是否有效 const savedToken pm.environment.get(“access_token”); const expireTime pm.environment.get(“token_expire_time”); if (!savedToken || !expireTime || Date.now() parseInt(expireTime)) { console.log(‘Token无效或已过期正在获取新Token...’); // 异步获取Token获取成功后会自动设置环境变量然后发送主请求 getAccessToken(function() { // 这个回调函数里主请求会自动使用新设置的access_token环境变量 // 因为主请求的Header里可能配置了Authorization: Bearer {{access_token}} console.log(‘Token准备就绪继续主请求。’); }); } else { console.log(‘使用缓存的Token。’); // 直接继续主请求会使用现有的Token }重要提示pm.sendRequest是异步的。主请求会等待这个异步回调函数callback被调用后才会发出。上面例子通过回调函数确保了执行顺序。在集合运行器中使用时需要特别注意这种异步操作避免请求间依赖出错。5.3 流程控制setNextRequest这个功能主要用于集合运行器Collection Runner。它允许你在一个请求的测试脚本Tests中指定下一个要执行的请求。这可以用来实现简单的业务流程测试比如“注册 - 登录 - 查询个人信息”。假设你的集合中有三个请求Register(注册)Login(登录)GetProfile(获取资料)你可以在Register请求的Tests脚本里写// 检查注册是否成功 if (pm.response.code 200) { const jsonData pm.response.json(); // 将注册成功的用户名密码存为变量供登录使用 pm.collectionVariables.set(“registered_username”, jsonData.username); pm.collectionVariables.set(“registered_password”, “test123”); // 假设密码已知 // 指定下一个运行 Login 请求 postman.setNextRequest(“Login”); } else { // 注册失败可以停止流程或重试 postman.setNextRequest(null); // null 表示停止迭代 }在Login请求的Tests脚本里if (pm.response.code 200) { const jsonData pm.response.json(); pm.collectionVariables.set(“access_token”, jsonData.token); // 指定下一个运行 GetProfile 请求 postman.setNextRequest(“GetProfile”); }在GetProfile请求的Tests脚本里通常设置为postman.setNextRequest(null);来结束流程。注意setNextRequest只在集合运行器中生效在手动发送单个请求时无效。它控制的是同一个迭代内的请求执行顺序。6. 调试、排错与最佳实践6.1 利用控制台进行高效调试Postman内置的控制台View - Show Postman Console是调试脚本的生命线。以下信息会被记录脚本中所有的console.log()、console.info()、console.warn()、console.error()输出。发送的请求详情包括最终生成的URL、Headers、Body。接收的响应详情状态码、响应头、响应体。脚本执行的错误信息。调试技巧关键变量打印在脚本的关键节点打印出变量的值尤其是参与签名计算的中间字符串。错误捕获使用try...catch包裹可能出错的代码块并在catch中打印错误信息。查看最终请求有时你以为脚本设置了某个头或参数但实际请求中没有。一定要在控制台查看“Request”部分确认最终发出的请求是否符合预期。6.2 常见问题与解决方案速查表问题现象可能原因排查步骤与解决方案变量{{var}}未被替换1. 变量名拼写错误。2. 变量作用域不对例如在请求URL中用{{var}}但变量是在脚本中用pm.variables.set设置的局部变量而你在其他地方引用。3. 变量值为undefined或null。1. 检查控制台看脚本是否执行变量是否成功设置打印出来。2. 确认变量作用域。在URL/Headers/Body中使用{{var}}时Postman会从所有作用域查找。最常用的是pm.variables.set局部和pm.environment.set环境。3. 确保设置变量的代码逻辑正确变量有值。pm.sendRequest回调不执行主请求卡住回调函数未被调用或回调函数内发生未捕获的错误。1. 确保pm.sendRequest的第二个参数回调函数正确定义。2. 在回调函数内部用try...catch包裹。3. 检查网络确保pm.sendRequest的请求本身能成功或失败触发回调。HMAC签名总是验证失败1.签名源串拼接规则与服务器端不一致95%的原因。2. 密钥(app_secret)错误。3. 参数编码问题如空格、特殊字符。4. 时间戳不同步。1.逐字符对比将脚本打印的signString和服务器端生成的进行对比。注意排序规则、是否包含多余空格或换行、是否包含域名等。2. 确认使用的app_secret环境变量值正确。3. 对参数值进行统一的URL编码或确认服务器端不要求编码。4. 检查服务器时间与本地时间是否相差过大。集合运行器执行顺序不符合预期对setNextRequest的理解有误或脚本逻辑错误导致流程跳转异常。1.setNextRequest只在当前迭代中生效。它指定的是当前迭代中下一个要执行的请求名。2. 确保请求名称Name与setNextRequest中字符串完全一致区分大小写。3. 在最后一个请求或想停止的地方使用postman.setNextRequest(null);。脚本语法错误导致请求无法发送JavaScript代码存在语法错误。1. 查看控制台会有红色的JavaScript错误信息指出哪一行出错。2. 检查括号、引号是否匹配变量名是否定义。3. 使用编辑器的语法高亮功能辅助检查。6.3 维护与协作最佳实践脚本模块化与注释对于复杂的集合将通用函数如签名函数、数据生成函数写在集合的预请求脚本中并添加清晰的注释说明输入、输出和用途。在单个请求的脚本中只写与该请求特异性相关的逻辑。善用环境变量这是Postman协作的基石。将服务器地址、密钥、通用账号等配置信息全部放入环境变量。将不含敏感信息的环境模板如dev.postman_environment.json提交到版本控制系统如Git团队成员导入后再各自在本地添加具体的密钥值。版本控制你的集合Postman集合.json文件是可以导出并放入Git进行版本控制的。这能记录脚本和接口的变更历史方便回滚和协作。为脚本编写简单的测试在请求的“Tests”标签页不仅可以测试响应也可以测试预请求脚本设置的一些变量是否正确。例如在签名请求的Tests里可以断言pm.request.headers.get(‘X-Signature’)不为空。性能考量预请求脚本会增加请求的发送延时。避免在脚本中执行非常耗时的同步操作如大型循环。对于pm.sendRequest要意识到它会使单次请求的耗时翻倍先发一个辅助请求。在设计测试套件时需权衡。预请求脚本将Postman从一个被动的调试工具转变为一个主动的、智能的接口交互引擎。掌握它意味着你掌握了接口测试自动化的第一把利器。从简单的变量设置到复杂的链式认证每一步的自动化都代表着效率的提升和人为错误的减少。花时间打磨你的脚本它会在未来的项目测试中成倍地回报你。
返回列表