1. 项目概述:为什么需要录制手机APP的接口测试脚本?
作为一名在测试领域摸爬滚打了十多年的老鸟,我见过太多测试同学在面对移动端APP接口测试时,还在用最原始的方式:打开Fiddler或Charles抓包,然后手动在JMeter里一个请求一个请求地复制粘贴URL、Header和Body。效率低不说,还容易出错,特别是遇到那些参数复杂、依赖Cookie或Token的接口,简直是噩梦。
所以,今天我想跟你分享一个能极大提升效率的“懒人”方法:用JMeter直接录制手机APP的操作,自动生成接口测试脚本。这不仅仅是把“抓包”和“写脚本”两个步骤合二为一,更重要的是,它能完整地记录下你操作APP时产生的所有网络请求,包括那些容易被忽略的静态资源请求、心跳包、埋点上报等,为你构建一个最贴近真实用户行为的测试场景打下坚实基础。
简单来说,这个方法的核心价值在于:自动化、保真度高、可复用性强。无论是给开发做冒烟测试,还是为性能测试准备基础脚本,亦或是做接口回归测试,它都能让你从重复的机械劳动中解放出来,把精力更多地放在测试用例设计和结果分析上。接下来,我就手把手带你走通整个流程,并分享一些我踩过坑才总结出来的实战经验。
2. 环境准备与核心原理拆解
在开始动手之前,我们必须把“舞台”搭好,并理解背后的工作原理。这样,当遇到问题时,你才能知道从哪里入手排查,而不是盲目地试错。
2.1 工具清单与安装要点
你需要准备以下几样东西:
- JMeter:主角,负责录制和生成脚本。建议从官网下载最新稳定版。安装就是解压,没什么难度。但有个关键点:确保你的电脑已经安装了合适版本的Java(JDK 8或11比较稳妥)。启动时如果报错,十有八九是Java环境问题。
- 测试手机:Android或iOS均可。本文将以Android为例,因为其代理设置更为通用。iOS的原理完全一样,只是在Wi-Fi代理设置上路径略有不同。
- 网络环境:确保你的电脑和手机连接在同一个局域网(Wi-Fi)下。这是整个方案能跑通的基础。你可以用电脑开热点给手机连,或者让手机和电脑都连上同一个路由器。
注意:很多公司内网有安全策略,可能会禁止或干扰代理流量。如果你在办公室操作失败,可以尝试切换到手机热点网络环境进行。
2.2 核心原理:代理(Proxy)是如何工作的?
录制脚本的本质,是让JMeter扮演一个“中间人”(Man-in-the-Middle)的角色。这个过程可以分解为三步:
- 拦截:你在JMeter中启动一个HTTP(S)代理服务器(默认端口8888)。然后,在手机的Wi-Fi设置中,手动配置代理,将代理服务器指向你电脑的IP地址和JMeter代理的端口。
- 转发与记录:此后,手机APP发出的所有HTTP/HTTPS网络请求,都会先被发送到你电脑上的JMeter代理服务器。
- 生成脚本:JMeter代理收到请求后,一方面会将请求原样转发给真正的目标服务器(APP的服务器),另一方面,它会把这个请求的所有细节(方法、URL、头信息、参数、Cookie等)记录下来,并自动转换成JMeter的采样器(如HTTP Request),保存到你指定的线程组中。
这就好比你要寄一封信(网络请求),本来直接投递到邮筒(服务器)就行。但现在你请了一位秘书(JMeter代理),你把信先给秘书,秘书复印一份存档(录制脚本),然后把原件寄出。手机APP和服务器之间的通信完全不受影响,但完整的“通信记录”已经在你手上了。
理解了这个,你就明白为什么必须保证电脑和手机在同一网络:因为手机需要能通过网络找到你电脑上运行的JMeter代理服务。
3. 详细操作步骤:从零开始录制第一个脚本
理论讲完,我们进入实战环节。我会以测试一个简单的“天气查询APP”为例,假设它的服务器接口是api.weather.com。
3.1 第一步:在JMeter中配置代理录制器
- 启动JMeter:进入你的JMeter解压目录的
bin文件夹,双击jmeter.bat(Windows) 或执行./jmeter(Mac/Linux) 启动。 - 创建测试计划(Test Plan):默认会新建一个。建议先保存,给它起个有意义的名字,比如
手机APP接口录制模板.jmx。 - 添加线程组(Thread Group):右键点击
Test Plan->Add->Threads (Users)->Thread Group。这个线程组将作为我们录制下来的请求的“容器”。你可以给它重命名为“录制容器”。 - 添加HTTP(S) Test Script Recorder:这是核心组件。右键点击
Test Plan(注意,不是线程组)->Add->Non-Test Elements->HTTP(S) Test Script Recorder。 - 配置代理录制器:
- Global Settings:
Port默认是8888,如果被占用可以改成其他,比如8899。记住这个端口号。 - Target Controller:选择我们刚才创建的“录制容器”线程组。这意味着录制的请求都会放到这个组里。
- HTTP(S) Test Script Recorder界面下方有几个标签页,我们重点关注
Requests Filtering:- Include Patterns:添加包含模式。比如我们的天气接口都是
/api/v1/*这样的,我们可以添加一个.*/api/v1/.*的正则表达式,这样只录制接口请求,过滤掉图片、CSS等静态资源。这是保持脚本整洁的关键一步! - Exclude Patterns:添加排除模式。如果你知道某些域名或路径肯定不需要,比如数据分析SDK的域名
sdk.analytics.com,可以在这里排除。
- Include Patterns:添加包含模式。比如我们的天气接口都是
- Start:先别急着点!我们需要先配置好证书(针对HTTPS)和手机端。
- Global Settings:
3.2 第二步:处理HTTPS流量(关键且易错)
现在的APP几乎全部使用HTTPS。JMeter要解密HTTPS流量,必须让手机“信任”它颁发的证书。
- 生成JMeter根证书:在JMeter的
bin目录下,有一个叫ApacheJMeterTemporaryRootCA.crt的文件。启动JMeter后,这个文件才会生成。如果找不到,你可以先点一下上一步的Start按钮,JMeter会提示你证书存放路径,通常就在bin目录下。 - 将证书发送到手机并安装:
- 你可以通过邮件、微信文件传输助手或数据线,把这个
.crt文件传到手机上。 - Android手机:在文件管理器中找到该证书,点击安装。系统会要求你给证书起个名字(比如“JMeter Proxy”),并选择用途,选择“VPN和应用”或“WLAN”均可。安装时可能需要输入锁屏密码。
- iOS手机:用Safari浏览器访问一个能下载该证书的链接(比如你把证书放在一个网页服务器上,或者用隔空投送),下载后进入
设置-通用-描述文件与设备管理,找到该证书并安装。安装后,还必须进入设置-通用-关于本机-证书信任设置,找到刚刚安装的JMeter根证书,手动开启完全信任。这一步很多人会漏掉!
- 你可以通过邮件、微信文件传输助手或数据线,把这个
实操心得:iOS的证书信任步骤是最大的坑。很多同学录不到HTTPS请求,就是因为只安装了证书,没去“证书信任设置”里开启信任。务必检查!
3.3 第三步:手机端配置代理
- 获取你电脑在局域网内的IP地址。
- Windows:在命令行输入
ipconfig,查看“无线局域网适配器 WLAN”或“以太网适配器”下的IPv4 地址。 - Mac/Linux:在终端输入
ifconfig或ip addr,找到对应网卡的inet地址。
- Windows:在命令行输入
- 在手机上,进入当前连接的Wi-Fi设置。
- Android:长按Wi-Fi网络 -> 修改网络 -> 高级选项 -> 代理 -> 选择“手动”。主机名填电脑IP,端口填JMeter代理设置的端口(默认8888)。
- iOS:点击Wi-Fi网络右边的
i图标 -> 配置代理 -> 选择“手动”。服务器填电脑IP,端口填8888。
- 保存设置。
3.4 第四步:开始录制与操作APP
- 回到JMeter,点击
HTTP(S) Test Script Recorder上的Start按钮。可能会弹出提示,直接点OK。 - 现在,JMeter的代理服务器已经开始在8888端口监听了。
- 操作你的手机APP。比如,打开天气APP,刷新天气,切换城市等。你所有的网络操作都会被JMeter捕获。
- 观察JMeter的“录制容器”线程组,你会看到采样器(Sampler)在不断增加,每个都代表一个被捕获的HTTP请求。
3.5 第五步:停止录制与清理
- 在APP上完成你想要录制的操作流程后,回到JMeter,点击
Stop按钮停止录制。 - 非常重要:立即回到手机Wi-Fi设置,将代理从“手动”改回“无”。否则,手机在断开当前Wi-Fi前都无法正常上网。
- 在JMeter中,右键点击“录制容器”线程组 ->
Save as,将录制好的脚本保存为.jmx文件。
至此,一个最基础的录制流程就完成了。你得到的是一个包含了所有请求的“毛坯”脚本。
4. 脚本优化与增强:从“能用”到“好用”
直接录制的脚本通常很“脏”,包含大量无关请求,且缺乏灵活性。我们需要对它进行加工。
4.1 请求清理与过滤
- 删除静态资源请求:通常
.js,.css,.png,.jpg,.gif,.ico等资源的请求对接口测试无意义。你可以根据URL后缀批量删除。在JMeter的“查看结果树”中预览,然后在线程组里右键删除。 - 合并重复请求:有些接口(如心跳包、上报)会被反复调用。对于测试来说,可能只需要保留一个样本。仔细检查,删除多余的。
- 使用“仅错误日志”:在测试计划层级添加一个监听器
View Results Tree,但在调试时将其设置为“仅错误日志”模式,可以避免录制时产生的海量成功请求日志拖慢JMeter。
4.2 参数化与关联
这是将录制脚本转化为可复用、健壮测试脚本的灵魂。
- 识别动态参数:查看录制的请求,找出那些每次运行都会变化的值。最常见的有:
token/authorization: 用户认证凭证。timestamp: 时间戳。nonce: 随机数。- 某些接口返回的ID,用于后续请求(如:创建订单返回
order_id,用于查询订单)。
- 使用变量替换:
- 对于
token, 你可以先录制一个登录请求,然后用JSON Extractor或正则表达式提取器后置处理器,从登录响应中提取token,存入一个JMeter变量(如${ACCESS_TOKEN})。 - 在后续所有需要
token的请求头或参数中,不再使用录制时的固定值,而是使用${ACCESS_TOKEN}。 - 对于时间戳,可以使用JMeter内置函数
${__time()}来动态生成。
- 对于
- 示例:提取Token
- 在登录请求下,添加后置处理器 ->
JSON Extractor。 Names of created variables: 填ACCESS_TOKEN。JSON Path Expressions: 填$.data.token(根据你登录接口实际的JSON结构来写)。Match No.: 填1。- 然后,在另一个需要认证的请求中,在Header Manager里添加一条:
Authorization: Bearer ${ACCESS_TOKEN}。
- 在登录请求下,添加后置处理器 ->
4.3 添加断言(Assertion)
没有断言的测试脚本是没有灵魂的。断言用来验证服务器的响应是否符合预期。
- 响应状态码断言:最基础的,确保返回200。添加
Response Assertion,测试字段选择“响应代码”,模式匹配规则“等于”,模式填200。 - 响应内容断言:更细粒度的检查。例如,登录成功后,响应JSON里通常会有
"code": 0或"success": true。添加JSON Assertion或Response Assertion来检查这些关键字段。 - 响应时间断言:添加
Duration Assertion,设置一个合理的最大响应时间阈值(如3000毫秒),用于性能基线测试。
4.4 组织测试结构
一个好的脚本应该结构清晰:
- 仅一次控制器(Once Only Controller):把登录请求放在这里面,保证整个线程组运行期间只登录一次。
- 事务控制器(Transaction Controller):把一个业务操作相关的多个请求组合在一起(比如“添加商品到购物车-结算-支付”)。事务控制器可以统计这组请求的总耗时,非常有用。
- 模块控制器(Module Controller):如果你有多个测试场景(如:浏览商品、下单、查看订单),可以把每个场景做成独立的“线程组”或“简单控制器”,然后用模块控制器来调用,实现脚本的模块化和复用。
5. 常见问题排查与实战技巧
录制过程中,你肯定会遇到各种问题。这里是我总结的“排坑指南”。
5.1 问题一:手机配置代理后,无法上网/APP无法连接网络
- 可能原因1:电脑防火墙阻止了JMeter代理端口。
- 解决:在电脑防火墙设置中,为JMeter(java.exe)或指定的端口(如8888)添加入站规则,允许连接。
- 可能原因2:电脑IP地址输入错误。
- 解决:确保你输入的是电脑在当前Wi-Fi下的局域网IP,而不是公网IP或127.0.0.1。
- 可能原因3:JMeter代理未成功启动。
- 解决:检查JMeter界面是否有错误提示。尝试更换一个端口(如8899),重启JMeter代理。
5.2 问题二:能抓到HTTP请求,但抓不到HTTPS请求(请求失败或内容为空)
- 可能原因1:手机未正确安装或信任JMeter根证书。(最常见!)
- 解决:严格按照上文“第二步”操作,特别是iOS用户,务必去“证书信任设置”里启用完全信任。
- 可能原因2:APP使用了证书绑定(SSL Pinning)。
- 解决:这是一种高级安全机制,APP只信任自己的证书,不信任用户安装的根证书。对于这类APP,常规代理录制方法失效。解决方案通常需要反编译APP并修改代码,这超出了基础测试范围,可能需要开发协助或使用更专业的移动测试工具。
- 可能原因3:JMeter的
HTTP(S) Test Script Recorder中未正确配置。- 解决:在Recorder的配置中,
HTTPS Domains可以填*(表示捕获所有HTTPS域名),但这不是必须的。更常见的是在Requests Filtering里确保没有错误地排除了你的目标域名。
- 解决:在Recorder的配置中,
5.3 问题三:录制到的请求太多太杂,包含大量图片、字体等资源
- 解决:充分利用
Requests Filtering。- 在
Include Patterns中,只添加你关心的接口路径模式,如.*/api/.*。 - 在
Exclude Patterns中,添加常见的静态资源后缀,如:.*\.js,.*\.css,.*\.png,.*\.jpg,.*\.gif,.*\.ico,.*\.woff,.*\.woff2。 - 这样,JMeter在录制时就会直接过滤掉这些请求,让你的脚本从一开始就保持干净。
- 在
5.4 问题四:录制的脚本回放失败(与录制时状态不一致)
- 可能原因1:参数未进行关联。比如登录后的
session或token是写死的,过期后脚本就失败了。- 解决:按照“4.2 参数化与关联”章节,将动态参数提取为变量。
- 可能原因2:请求顺序或依赖问题。某些请求需要前一个请求的返回结果作为参数。
- 解决:仔细分析业务逻辑,确保脚本中的请求顺序与真实操作一致,并正确提取依赖参数。
- 可能原因3:服务器有防爬虫或频率限制。
- 解决:在JMeter中增加合理的思考时间(
Timer),模拟真人操作间隔。检查请求头是否完整,特别是User-Agent、Referer等,有时服务器会校验这些信息。
- 解决:在JMeter中增加合理的思考时间(
5.5 高级技巧:使用Fiddler/Charles作为“前置代理”
有时,JMeter自带的代理录制器对某些复杂APP的支持不够好。你可以采用一个更稳定的组合方案:用Fiddler或Charles抓包,再导出为JMeter脚本。
- 用Fiddler/Charles正常抓取手机APP流量。这两个工具对HTTPS的支持和流量解析通常更友好。
- 在Fiddler/Charles中,将抓取到的会话(Session)全部选中。
- 导出这些会话。Fiddler可以导出为
SAZ文件,Charles可以导出为chls文件。 - 使用第三方工具(如
BlazeMeter的 Chrome 插件,或开源工具HAR to JMeter)将这些文件转换成JMeter的.jmx脚本。
这个方法的优点是录制过程更稳定直观,缺点是多了格式转换的步骤。你可以根据实际情况选择。
6. 将脚本投入实战:接口自动化与性能测试
一个优化好的录制脚本,其价值才刚刚开始体现。
用于接口自动化回归: 你可以将脚本保存为模板。以后每次发版,只需用这个脚本快速跑一遍核心业务流程,验证主要接口是否正常。结合JMeter的-n -t test.jmx -l result.jtl命令行模式,可以轻松集成到Jenkins等CI/CD流水线中,实现每日构建后的自动接口回归测试。
用于性能测试准备: 录制脚本是构建性能测试场景的第一步。你需要:
- 参数化:将用户、商品ID等数据放入CSV文件,使用
CSV Data Set Config来读取,模拟不同用户的行为。 - 控制并发:调整线程组的“线程数”(用户数)、“循环次数”和“Ramp-Up时间”。
- 添加监听器:添加
Aggregate Report、Response Times Graph等监听器,用于分析性能结果。 - 分布式测试:如果单台机器压力不够,可以使用JMeter的分布式测试功能,用多台机器同时施压。
从我个人的经验来看,花时间掌握“录制-优化”这套组合拳,前期看似多了一步,但从整个测试活动的生命周期来看,它节省的时间是巨大的,特别是当业务频繁迭代,接口经常变动时,你可以快速重新录制、对比、更新脚本,维护成本远低于完全手写。记住,好的测试工程师不仅是问题的发现者,更是效率的创造者。