前言

上一篇文章我们系统讲了接口测试的基础——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和环境变量

  1. Postman中Collection右键 → Export → 选择Collection v2.1格式 → 保存为 user_api_collection.json
  2. 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-5

Step 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
fi

Step 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做接口压力测试,敬请期待!


系列文章导航

  1. [测试用例设计方法论:从等价类到因果图的实战指南]
  2. [测试策略与测试计划制定:新项目如何规划测试]
  3. [从需求到高质量用例:手把手教你拆解需求]
  4. [Bug报告与缺陷管理规范:如何写出让开发无法拒绝的Bug单]
  5. [APP专项测试实战:安装/卸载/弱网/兼容/中断/埋点全覆盖]
  6. [Web端测试实战(含接口测试核心章节)]
  7. ← 本文:接口自动化测试实战:Postman+Newman+Jenkins
  8. 性能测试入门(即将更新)
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐