接口自动化测试实战:Postman+Newman+Jenkins从入门到落地
前言
上一篇文章我们系统讲了接口测试的基础——HTTP协议、状态码、请求头、用例设计、F12抓包。但手工测接口有个痛点:每次发版都要把几十上百个接口全部重跑一遍,耗时耗力还容易漏。
本文是Web测试系列第七篇,手把手带你用Postman + Newman + Jenkins搭建一套可落地的接口自动化测试体系。从最基础的断言脚本写起,到动态token处理、数据驱动测试、HTML报告生成,最后集成到Jenkins实现一键回归。全程可复制、可执行,看完就能用。
📋 一、为什么要做接口自动化?
1.1 手工测试 vs 自动化测试
| 维度 | 手工接口测试 | 自动化接口测试 |
|---|---|---|
| 执行方式 | 人工在Postman逐条点击Send | 脚本自动运行 |
| 执行效率 | 100条用例约30分钟 | 100条用例约30秒 |
| 回归成本 | 每次发版重跑一遍 | 一键执行,零人力 |
| 遗漏风险 | 容易漏测、忘记测 | 全量覆盖,零遗漏 |
| 执行时间 | 只能工作时间跑 | 凌晨定时跑、CI触发跑 |
| 结果记录 | 人工截图记录 | 自动生成HTML报告 |
| 新人接手 | 需要文档和口述 | 脚本即文档,跑一遍就懂 |
1.2 什么时候该做接口自动化?
| 场景 | 建议 |
|---|---|
| 项目初期,接口频繁变动 | ❌ 先别做,手工测更灵活 |
| 核心功能已稳定 | ✅ 优先覆盖核心接口 |
| 每次发版都要回归 | ✅ 必须做 |
| 接口数量多(50+) | ✅ 强烈建议 |
| 团队有CI/CD流水线 | ✅ 集成进去效果翻倍 |
| 一次性项目或短期项目 | ❌ 投入产出比不高 |
1.3 接口自动化工具选型
| 工具组合 | 上手难度 | 适用人群 | 特点 |
|---|---|---|---|
| Postman + Newman | ⭐ 低 | 手工测试转自动化 | 可视化+脚本,学习曲线平缓 |
| JMeter | ⭐⭐ 中 | 性能+接口测试 | Java生态,性能测试强 |
| Python + Requests + Pytest | ⭐⭐⭐ 高 | 有编程基础的测试 | 灵活度最高,可做复杂逻辑 |
| Apifox CLI | ⭐ 低 | Apifox用户 | 国产一站式 |
📝本文选择 Postman + Newman,原因很简单:大多数手工测试工程师已经在用Postman做接口调试了,只需加上Tests脚本和Newman就能实现自动化,几乎零额外学习成本。
🔧 二、环境搭建(5分钟搞定)
2.1 安装Node.js
Newman依赖Node.js,先去官网下载安装。
# 安装完成后验证 node -v # 应显示 v18.x 或更高 npm -v # 应显示 9.x 或更高2.2 安装Newman
bash
# 全局安装Newman npm install -g newman # 验证安装 newman -v # 应显示版本号2.3 安装HTML报告插件(htmlextra)
bash
# 安装增强版HTML报告插件 npm install -g newman-reporter-htmlextra装完这三样就完成了环境搭建,不超过5分钟。
📝 三、编写你的第一个接口测试脚本
3.1 从Collection开始
以一个用户管理系统为例,创建以下接口集合:
📁 用户管理系统 ├── 📁 登录模块 │ └── POST 登录 ├── 📁 用户管理 │ ├── GET 查询用户列表 │ ├── GET 查询用户详情 │ ├── POST 新增用户 │ ├── PUT 修改用户 │ └── DELETE 删除用户 └── 📁 退出模块 └── POST 退出登录3.2 编写第一条Tests断言
以「POST 登录」接口为例,在Postman的Tests标签页写断言脚本:
javascript
// ========== 基础断言 ========== // 1. 校验状态码 pm.test("状态码为200", function () { pm.response.to.have.status(200); }); // 2. 校验响应时间 pm.test("响应时间小于2秒", function () { pm.expect(pm.response.responseTime).to.be.below(2000); }); // 3. 校验返回体是JSON格式 pm.test("返回格式为JSON", function () { pm.response.to.have.jsonBody(); }); // ========== 字段校验 ========== // 4. 校验code字段 pm.test("code等于200", function () { var jsonData = pm.response.json(); pm.expect(jsonData.code).to.eql(200); }); // 5. 校验message字段存在且不为空 pm.test("message字段不为空", function () { var jsonData = pm.response.json(); pm.expect(jsonData.message).to.not.be.empty; }); // 6. 校验data.token存在 pm.test("返回了token", function () { var jsonData = pm.response.json(); pm.expect(jsonData.data).to.have.property("token"); pm.expect(jsonData.data.token).to.be.a("string").and.not.empty; }); // ========== 提取变量供后续接口使用 ========== // 7. 将token存入环境变量 var jsonData = pm.response.json(); pm.environment.set("token", jsonData.data.token); // 8. 将用户ID存入环境变量 pm.environment.set("userId", jsonData.data.userId);📝断言三步法:每个接口至少覆盖——①状态码 ②核心返回字段 ③关键业务值。
3.3 运行Collection验证
点击Postman左上角Collection名称旁的 ▶ 按钮 → Run → 勾选所有接口 → Run,查看执行结果。
所有用例都PASS才表示脚本编写正确。
🔗 四、接口关联:动态Token自动获取
接口自动化最大的痛点之一:token会过期,每次都要手动登录获取。Pre-request Script可以完美解决。
4.1 在Collection级别设置Pre-request Script
在Collection上右键 → Edit → Pre-request Script:
javascript
// 每次执行Collection时自动登录获取token // 判断token是否已存在且未过期 const tokenExpiry = pm.environment.get("token_expiry"); const now = Date.now(); if (!tokenExpiry || now > Number(tokenExpiry)) { console.log("Token不存在或已过期,正在自动登录..."); pm.sendRequest({ url: pm.environment.get("base_url") + "/api/user/login", method: "POST", header: { "Content-Type": "application/json" }, body: { mode: "raw", raw: JSON.stringify({ username: pm.environment.get("test_username"), password: pm.environment.get("test_password") }) } }, function (err, res) { if (err) { console.error("登录失败:", err); return; } var jsonData = res.json(); if (jsonData.code === 200) { pm.environment.set("token", jsonData.data.token); // 设置token过期时间(假设2小时后过期) pm.environment.set("token_expiry", String(now + 2 * 60 * 60 * 1000)); console.log("Token自动获取成功!"); } else { console.error("登录失败:", jsonData.message); } }); }4.2 在接口中使用Token
在每个需要认证的接口Headers中设置:
| Key | Value |
|---|---|
| Authorization | Bearer {{token}} |
| Content-Type | application/json |
📝{{token}}是Postman的变量引用语法,运行时自动替换为环境变量中的实际值。
4.3 变量作用域一览
| 作用域 | 设置方式 | 生命周期 | 适用场景 |
|---|---|---|---|
| Global | pm.globals.set() | 全局,所有Collection共享 | 很少用,容易变量污染 |
| Collection | pm.collectionVariables.set() | 当前Collection内 | Collection级别的配置 |
| Environment | pm.environment.set() | 当前环境 | 环境相关的配置(推荐) |
| Data | CSV/JSON数据文件 | 当前迭代 | 数据驱动测试 |
| Local | pm.variables.set() | 当前请求/脚本 | 临时变量 |
📝推荐做法:测试环境URL、账号密码、token等放在Environment变量中,便于切换环境。
📊 五、数据驱动测试:用CSV批量跑数据
5.1 什么是数据驱动测试?
同一个接口,用不同的数据反复执行。例如注册接口,需要测试各种用户名、密码的组合——不用写多条用例,一条用例 + 一个CSV文件即可。
5.2 准备CSV数据文件
新建register_testdata.csv:
csv
username,password,email,expected_code,expected_msg normal_user,Pass1234,user1@test.com,201,注册成功 short,Pass1234,user2@test.com,422,用户名长度不足 toolongusername123456789,Pass1234,user3@test.com,422,用户名长度超限 ,,user4@test.com,422,用户名不能为空 normal_user2,weak,user5@test.com,422,密码强度不足 normal_user3,Pass1234,invalid_email,422,邮箱格式不正确 normal_user4,Pass1234,,422,邮箱不能为空5.3 编写参数化Tests脚本
javascript
// 从CSV数据文件读取期望值 var expectedCode = parseInt(pm.iterationData.get("expected_code")); var expectedMsg = pm.iterationData.get("expected_msg"); // 校验状态码 pm.test("状态码为" + expectedCode, function () { pm.response.to.have.status(expectedCode); }); // 校验返回消息 pm.test("返回消息包含:" + expectedMsg, function () { var jsonData = pm.response.json(); pm.expect(jsonData.message).to.include(expectedMsg); }); // 如果是注册成功(201),额外校验返回字段 if (expectedCode === 201) { pm.test("注册成功返回用户ID", function () { var jsonData = pm.response.json(); pm.expect(jsonData.data).to.have.property("userId"); }); }5.4 运行数据驱动测试
Postman Collection Runner → Select File → 选择CSV文件 → Run。
Postman会自动用CSV中每一行数据执行一次请求,结果中会显示每行的通过/失败状态。
📝数据驱动测试核心:
- CSV第一行是变量名(与
pm.iterationData.get()中的名称对应) - 每个变量一行,Postman自动遍历
- 可以混合正向和反向用例
5.4 运行数据驱动测试
Postman Collection Runner → Select File → 选择CSV文件 → Run。
Postman会自动用CSV中每一行数据执行一次请求,结果中会显示每行的通过/失败状态。
📝数据驱动测试核心:
- CSV第一行是变量名(与
pm.iterationData.get()中的名称对应) - 每个变量一行,Postman自动遍历
- 可以混合正向和反向用例
🔄 六、接口链式调用:增→查→改→删全流程
真实业务场景中,接口之间存在依赖关系。比如:新增用户 → 查询用户 → 修改用户 → 删除用户。
6.1 链式调用实现思路
POST 新增用户 → 提取返回的userId ↓ GET 查询用户详情 → 使用上一步的userId ↓ PUT 修改用户 → 使用上一步的userId ↓ DELETE 删除用户 → 使用上一步的userId ↓ GET 查询用户详情 → 验证已删除(返回404)6.2 各接口Tests脚本
POST 新增用户:
javascript
pm.test("新增用户成功", function () { pm.response.to.have.status(201); var jsonData = pm.response.json(); // 将返回的userId存入环境变量,供后续接口使用 pm.environment.set("newUserId", jsonData.data.userId); console.log("新增用户ID:", jsonData.data.userId); });GET 查询用户详情:
URL使用变量:GET {{base_url}}/api/user/{{newUserId}}
javascript
pm.test("查询到刚创建的用户", function () { pm.response.to.have.status(200); var jsonData = pm.response.json(); pm.expect(jsonData.data.userId).to.eql(pm.environment.get("newUserId")); });PUT 修改用户:
javascript
pm.test("修改用户成功", function () { pm.response.to.have.status(200); var jsonData = pm.response.json(); pm.expect(jsonData.message).to.include("成功"); });DELETE 删除用户:
javascript
pm.test("删除用户成功", function () { pm.response.to.have.status(200); });GET 再次查询(验证已删除):
javascript
pm.test("用户已被删除", function () { pm.response.to.have.status(404); });📝链式调用的关键:
- 上游接口在Tests中通过
pm.environment.set()提取关键数据 - 下游接口通过
{{变量名}}引用 - 接口执行顺序按Collection中的排列顺序(可在Runner中调整)
🚀 七、Newman命令行执行与HTML报告
7.1 导出Collection和环境变量
- Postman中Collection右键 → Export → 选择Collection v2.1格式 → 保存为
user_api_collection.json - Postman右上角环境选择器 → Manage Environments → 导出 → 保存为
test_env.json
7.2 Newman基础命令
bash
# 最基础的执行 newman run user_api_collection.json # 指定环境变量 newman run user_api_collection.json -e test_env.json # 指定数据文件 newman run user_api_collection.json -e test_env.json -d register_testdata.csv # 指定迭代次数 newman run user_api_collection.json -e test_env.json -n 3 # 生成HTML报告(htmlextra) newman run user_api_collection.json \ -e test_env.json \ -r htmlextra \ --reporter-htmlextra-title "用户管理系统-接口测试报告" \ --reporter-htmlextra-browserTitle "API Test Report"7.3 常用参数速查
| 参数 | 说明 | 示例 |
|---|---|---|
-e | 指定环境变量文件 | -e test_env.json |
-g | 指定全局变量文件 | -g globals.json |
-d | 指定数据驱动文件 | -d testdata.csv |
-n | 迭代次数 | -n 5 |
-r | 报告格式 | -r cli,htmlextra,junit |
--delay-request | 请求间隔(毫秒) | --delay-request 500 |
--timeout-request | 请求超时(毫秒) | --timeout-request 10000 |
--folder | 只运行指定文件夹 | --folder "登录模块" |
--bail | 遇到失败就停止 | 不加参数默认继续执行 |
7.4 报告解读
执行后会在当前目录生成newman/文件夹,打开里面的HTML文件即可看到:
| 报告内容 | 说明 |
|---|---|
| 总览 | 总请求数、通过数、失败数、跳过数 |
| 通过率 | 百分比展示,一眼看出质量 |
| 响应时间 | 平均/最小/最大响应时间 |
| 失败详情 | 哪个请求失败了、断言哪条没通过 |
| 每个请求详情 | 请求URL、请求头、请求体、响应体、断言结果 |
🤖 八、Jenkins集成:实现CI/CD自动化回归
8.1 Jenkins配置步骤
Step 1:安装必要插件
- NodeJS Plugin(提供Node环境)
- HTML Publisher Plugin(展示HTML报告)
Step 2:配置NodeJS环境
Jenkins → Manage Jenkins → Global Tool Configuration → NodeJS → 新增安装 → 选择Node版本
Step 3:创建自由风格任务
新建Item → Freestyle project → 输入任务名称
Step 4:配置定时构建
构建触发器 → Build periodically:
# 每天早上8点执行 H 8 * * * # 每4小时执行一次 H */4 * * * # 工作日每小时执行 H * * * 1-5Step 5:配置构建步骤
添加构建步骤 → Execute shell(Linux)或 Execute Windows batch command(Windows):
bash
# 安装依赖(首次需要) npm install -g newman newman-reporter-htmlextra # 执行接口自动化测试 newman run user_api_collection.json \ -e test_env.json \ -r cli,htmlextra,junit \ --reporter-htmlextra-title "用户管理系统-接口回归测试" \ --reporter-htmlextra-browserTitle "API Test" \ --reporter-junit-export junit-report.xml # 检查退出码,非0表示有用例失败 if [ $? -ne 0 ]; then echo "接口测试有失败用例,请检查!" exit 1 fiStep 6:配置HTML报告展示
构建后操作 → Publish HTML reports:
| 配置项 | 值 |
|---|---|
| HTML directory to archive | newman/ |
| Index page(s) | *.html |
| Report title | 接口自动化测试报告 |
Step 7:配置邮件通知
构建后操作 → Editable Email Notification,在构建失败时自动发送邮件。
8.2 Jenkins CI/CD流水线示意图
代码提交(Git Push) ↓ 触发Jenkins构建 ↓ 拉取最新代码 + 接口测试脚本 ↓ Newman执行接口自动化 ↓ 生成HTML报告 + JUnit报告 ↓ 判断结果 ├── 全部通过 → ✅ 构建成功 → 自动部署 └── 有失败 → ❌ 构建失败 → 发送邮件通知 → 阻止部署📋 九、实战案例:电商下单流程接口自动化
9.1 接口链路
1. POST 登录 → 获取token 2. GET 搜索商品 → 获取商品ID 3. GET 商品详情 → 校验库存 4. POST 加入购物车 → 获取购物车项ID 5. POST 创建订单 → 获取订单ID 6. GET 查询订单 → 校验订单状态 7. POST 支付订单 → 模拟支付 8. GET 查询订单 → 校验状态变为"已支付"9.2 完整Tests脚本
POST 登录:
javascript
pm.test("登录成功", function () { pm.response.to.have.status(200); var jsonData = pm.response.json(); pm.expect(jsonData.code).to.eql(200); pm.environment.set("token", jsonData.data.token); console.log("Token获取成功"); });GET 搜索商品:
javascript
pm.test("搜索商品成功", function () { pm.response.to.have.status(200); var jsonData = pm.response.json(); pm.expect(jsonData.data.list).to.be.an("array").that.is.not.empty; // 取第一个商品的ID pm.environment.set("productId", jsonData.data.list[0].productId); console.log("商品ID:", jsonData.data.list[0].productId); });GET 商品详情:
javascript
pm.test("商品详情查询成功", function () { pm.response.to.have.status(200); var jsonData = pm.response.json(); pm.expect(jsonData.data.stock).to.be.greaterThan(0); // 库存大于0 pm.environment.set("productPrice", jsonData.data.price); });POST 加入购物车:
javascript
pm.test("加入购物车成功", function () { pm.response.to.have.status(200); var jsonData = pm.response.json(); pm.environment.set("cartItemId", jsonData.data.cartItemId); });POST 创建订单:
javascript
pm.test("创建订单成功", function () { pm.response.to.have.status(201); var jsonData = pm.response.json(); pm.expect(jsonData.data.totalAmount).to.eql(pm.environment.get("productPrice")); pm.environment.set("orderId", jsonData.data.orderId); console.log("订单ID:", jsonData.data.orderId); });GET 查询订单:
javascript
pm.test("订单状态为待支付", function () { pm.response.to.have.status(200); var jsonData = pm.response.json(); pm.expect(jsonData.data.status).to.eql("UNPAID"); });POST 支付订单:
javascript
pm.test("支付成功", function () { pm.response.to.have.status(200); var jsonData = pm.response.json(); pm.expect(jsonData.message).to.include("成功"); });GET 查询订单(再次查询验证状态变更):
javascript
pm.test("订单状态变更为已支付", function () { pm.response.to.have.status(200); var jsonData = pm.response.json(); pm.expect(jsonData.data.status).to.eql("PAID"); });9.3 执行命令
bash
newman run ecommerce_collection.json \ -e ecommerce_env.json \ -r htmlextra \ --reporter-htmlextra-title "电商下单流程-接口自动化测试"⚠️ 十、常见问题与避坑指南
| 问题 | 原因 | 解决方法 |
|---|---|---|
| Token过期导致后续接口全部401 | Token在Collection执行中途过期 | Pre-request Script中检查token时效,过期自动重新登录 |
| 数据驱动CSV文件中文乱码 | CSV编码不是UTF-8 | 用记事本另存为 → 编码选UTF-8 |
Newman报collection could not be loaded | Collection导出格式不对 | 导出时选Collection v2.1格式 |
| 环境变量取不到值 | 变量作用域不对或拼写错误 | 检查变量名大小写、确认set时用的正确作用域 |
| 链式调用中间某步失败,后面全挂 | 缺少错误处理 | 关键步骤加try-catch或设置默认值 |
| 报告生成路径错误 | -r htmlextra没加或插件没装 | npm install -g newman-reporter-htmlextra |
| Jenkins构建找不到newman | Jenkins服务器没装Node或路径不对 | 用NodeJS Plugin管理Node环境 |
| 断言写错语法 | Postman的Tests用的是简化的Chai语法 | 语法参考:pm.expect().to.xxx,不是完整的Chai |
🧠 十一、记忆口诀
接口自动化五步走
断言先行定标准——先写Tests脚本,定义什么算通过 变量关联串流程——token、userId用变量串联 数据驱动提效率——CSV批量跑正向反向用例 命令行跑出报告——Newman一键执行生成HTML Jenkins定时全自动——CI/CD流水线解放双手
📝 写在最后
接口自动化测试不是一蹴而就的,建议分阶段推进:
| 阶段 | 目标 | 时间 |
|---|---|---|
| 第一阶段 | 核心接口 + 基础断言(状态码+核心字段) | 第1周 |
| 第二阶段 | 动态Token + 接口链式调用 | 第2周 |
| 第三阶段 | 数据驱动测试(CSV参数化) | 第3周 |
| 第四阶段 | Newman命令行执行 + HTML报告 | 第4周 |
| 第五阶段 | Jenkins集成 + 定时构建 + 邮件通知 | 第5周 |
从第一条断言脚本开始,一步一个脚印,你的接口自动化体系就会慢慢建立起来。
下一篇我们将进入性能测试入门领域,教你如何用JMeter做接口压力测试,敬请期待!
系列文章导航
- [测试用例设计方法论:从等价类到因果图的实战指南]
- [测试策略与测试计划制定:新项目如何规划测试]
- [从需求到高质量用例:手把手教你拆解需求]
- [Bug报告与缺陷管理规范:如何写出让开发无法拒绝的Bug单]
- [APP专项测试实战:安装/卸载/弱网/兼容/中断/埋点全覆盖]
- [Web端测试实战(含接口测试核心章节)]
- ← 本文:接口自动化测试实战:Postman+Newman+Jenkins
- 性能测试入门(即将更新)
