微信小程序测试相关
微信小程序测试 完整系统学习大纲
本文面向测试工程师,按”认知 → 环境 → 专项测试点 → 性能 → 自动化 → 兼容 → 常见问题”的顺序组织,由浅入深。 小程序不是”手机上的网页”,也不是原生 App——它有自己的双线程架构、生命周期、路由栈、授权体系和审核规范。功能测试能覆盖一半,另一半必须靠这些专属知识。
一、小程序概述与测试特点
1.1 什么是微信小程序?
- 定义:运行在微信客户端内部的轻量级应用,2017 年发布,无需下载安装,用完即走。
- 技术栈:
WXML(结构)+WXSS(样式)+JS(逻辑)+JSON(配置),开发体验接近前端,但没有 DOM 和 BOM。 - 运行环境:微信客户端提供的基础库(微信版本决定基础库版本范围)。
1.2 小程序 vs App vs H5
| 维度 | 小程序 | 原生 App | H5(手机网页) |
|---|---|---|---|
| 安装 | 无需安装 | 需下载安装 | 无需 |
| 入口 | 微信内(扫码/分享/搜索/下拉) | 桌面图标 | 浏览器/微信内打开 |
| 审核 | 需微信审核 | 应用商店审核 | 无 |
| 能力 | 微信开放能力(支付/登录/订阅消息) | 系统全部能力 | 受限 |
| 性能 | 接近原生(双线程 + 原生组件) | 最优 | 一般 |
| 更新 | 服务端发版,用户无感 | 需重新下载 | 实时 |
| 体积 | 主包 ≤ 2MB | 无硬限制 | 无 |
| 跨平台 | 一套代码 iOS+Android | 两套 | 一套 |
💡 测试含义:小程序没有安装卸载,所以”安装测试”变成”首次打开/版本更新测试”;没有应用商店,所以审核规范成了必须测的一项。
1.3 技术架构(双线程模型)
┌──────────────────────────────────────────────┐
│ 视图层(WebView / Skyline) │
│ · 渲染 WXML + WXSS │
│ · 可以有多个(每个页面一个) │
└───────────────┬──────────────────────────────┘
│ ① setData 传数据
│ ② 事件绑定回传
┌───────────────┴──────────────────────────────┐
│ Native 层(微信客户端 / WeixinJSBridge) │
│ · 中转通信、转发原生能力(支付/定位/相机) │
└───────────────┬──────────────────────────────┘
│
┌───────────────┴──────────────────────────────┐
│ 逻辑层(AppService,JSCore) │
│ · 执行 JS、处理数据、调 wx.xxx API │
│ · 无 DOM、无 BOM、无 window/document │
└──────────────────────────────────────────────┘
对测试的影响:
| 架构特点 | 引发的问题 |
|---|---|
| 逻辑层与视图层分离通信 | setData 是性能瓶颈,数据量大/调用频繁会卡顿 |
| 无 DOM | 传统 Web 自动化(Selenium)不能直接操作 |
| 依赖微信基础库 | 基础库版本兼容是线上问题高发区 |
| 页面栈最多 10 层 | 连续跳转超过 10 层后 navigateTo 失败 |
| 原生组件层级最高 | video/map/canvas 会盖住普通元素(z-index 失效) |
1.4 小程序的三种版本
| 版本 | 来源 | 谁能访问 | 测试用途 |
|---|---|---|---|
| 开发版 | 开发者工具”预览”生成的二维码 | 开发者本人 + 项目成员 | 开发自测 |
| 体验版 | 开发者工具”上传”,后台设为体验版 | 体验成员(需在后台配置) | ★ 测试主用 |
| 正式版 | 提交审核通过并发布 | 全部微信用户 | 线上验证 |
⚠️ 测试同学第一件事:把自己加进小程序后台的”成员管理 → 体验成员”,否则扫不了体验版二维码。
二、测试环境准备
2.1 微信开发者工具
| 功能 | 用途 |
|---|---|
| 模拟器 | 快速验证 UI、切换机型/分辨率 |
| 调试器(Console/Sources/Network/Storage) | 查日志、断点、看请求、看缓存 |
| Compiler | 编译模式(可配置启动页面与启动参数 ★) |
| Audits / 体验评分 | 自动跑性能评分 |
| 真机调试 | 手机扫码后,实时看手机上的日志与 DOM |
| 上传 / 预览 | 产出体验版与开发版二维码 |
关键配置(测试要会):
编译模式(重要)
开发者工具 → 编译模式 → 添加编译模式
· 启动页面:直接进某个深页面(不用一步步点进去)
· 启动参数:模拟场景值、URL 参数(如 ?id=123&from=share)
→ 测试深页面、分享入口、扫码入参时必备
不校验合法域名
详情 → 本地设置 → 勾选"不校验合法域名、web-view、TLS 版本以及 HTTPS 证书"
⚠️ 这是调试用的开关,正式环境必须关闭并配置正确的域名白名单
2.2 真机调试与日志
方法一:开发者工具 → 真机调试 → 手机扫码 → 电脑上看手机日志
方法二:手机上打开"调试"
小程序右上角 ⋯ → 打开调试(开发版/体验版才有)
→ 重新进入小程序,右下角出现 vConsole 按钮
→ 可看 Console / Network / Storage / System 信息
方法三:抓包(见第 8 章)
2.3 测试号与体验版
| 类型 | 限制 | 适用 |
|---|---|---|
| 测试号(无 AppID) | 部分能力不可用(支付、订阅消息等) | 学习、demo |
| 有 AppID 的开发/体验版 | 能力完整 | ★ 正式项目测试 |
三、小程序专项测试点(重点)
3.1 生命周期与页面栈
应用生命周期:
| 回调 | 触发时机 | 测试点 |
|---|---|---|
onLaunch |
小程序初始化(全局一次) | 全局数据、登录态初始化 |
onShow |
启动或从后台切前台 | 切后台再回来数据是否刷新 |
onHide |
切后台 | 是否暂停定时器/音视频 |
onError |
JS 错误 | 是否有上报 |
onPageNotFound |
页面不存在 | 是否有兜底页 |
页面生命周期:
onLoad( options ) 页面加载,可拿到 URL 参数 ★
onShow 页面显示(每次切前台/返回都触发)
onReady 首次渲染完成
onHide 页面隐藏(navigateTo 到新页、切后台)
onUnload 页面卸载(redirectTo / navigateBack)
💡 高频 Bug:把”每次进入都要刷新”的逻辑写在
onLoad里,但从子页面返回时只触发onShow不触发onLoad→ 数据不刷新。 测试方法:A 页 → 进入 B 页修改数据 → 返回 A 页 → 看 A 页数据是否已更新。
页面栈(最多 10 层):
| API | 行为 | 页面栈 |
|---|---|---|
wx.navigateTo |
保留当前页,跳转 | +1(上限 10 层) |
wx.redirectTo |
关闭当前页,替换 | 不变 |
wx.switchTab |
跳 tabBar 页(不能带参数) | 清空非 tab 页 |
wx.reLaunch |
关闭所有页面,打开新页 | 清空 |
wx.navigateBack |
返回(delta 指定层数) | -delta |
测试点:
- 连续跳转 10 层后,第 11 次
navigateTo是否失败并有兜底 switchTab传参数会丢失(验证开发是否用了别的方案传值)navigateBack返回后数据是否刷新- 支付完成后用
redirectTo/reLaunch而非navigateTo(避免返回到支付页重复支付)
3.2 入口与场景值(小程序特有)
场景值 scene 标识用户从哪个入口进来,通过 onLoad(options) / wx.getLaunchOptionsSync() 获取:
| scene | 入口 | 测试必测 |
|---|---|---|
| 1001 | 发现页”小程序”主入口 | ★ |
| 1011 | 扫描二维码 | ★ |
| 1007 / 1008 | 好友/群聊会话中的小程序卡片 | ★ |
| 1035 | 公众号自定义菜单 | ★ |
| 1036 | App 分享消息卡片 | |
| 1058 | 公众号文章 | |
| 1089 | 微信聊天主界面下拉 | |
| 1014 | 小程序码(圆形) | ★ |
测试矩阵:
□ 扫码进入(二维码 + 小程序码,带 scene 参数)
□ 分享卡片进入(好友 / 群聊)
□ 公众号菜单 / 文章进入
□ 微信搜索进入
□ 下拉"最近使用"进入
□ 朋友圈("分享到朋友圈"是单页模式,能力受限 ★)
□ 直接打开(已使用过的小程序)
□ 外部 App 跳转
每个入口都要验证:
· 页面是否正确(是否按场景跳转到对应页,而非首页)
· scene 参数是否正确解析(如扫码带 id=123 是否直达详情页)
· 未登录时的处理(分享给新用户,是否需要先授权)
⚠️ 高频 Bug:分享卡片带
?id=123,但打开后总是跳首页 —— 因为参数写在onLoad处理的 page 路径上,而分享的 path 没带参数。
3.3 授权与登录
登录流程(必须理解,接口测试用得上):
① 小程序 wx.login() → 拿到临时凭证 code(5 分钟有效,只能用一次)
② code 发给开发者服务器
③ 服务器用 code + appid + secret 调微信 jscode2session 接口
→ 返回 openid + session_key(+ unionid,若绑定开放平台)
④ 服务器生成自定义登录态(token)返回小程序
⑤ 小程序存 storage,后续请求带 token
授权类型:
| 授权 | API / 组件 | 测试点 |
|---|---|---|
| 用户信息 | <button open-type="getUserInfo"> / wx.getUserProfile |
头像昵称获取(现多用头像昵称填写能力) |
| 手机号 | <button open-type="getPhoneNumber"> |
需企业主体,解密失败的处理 |
| 位置 | wx.getLocation / wx.chooseLocation |
拒绝授权、系统定位未开 |
| 相册/相机 | wx.chooseImage / wx.chooseMedia |
拒绝授权后再次唤起 |
| 麦克风/录音 | wx.getRecorderManager |
权限拒绝提示 |
| 蓝牙/通讯录/日历 | 各自 API | 同上 |
| 订阅消息 | wx.requestSubscribeMessage |
勾选”总是保持以上选择”的行为 |
授权测试标准动作(每个授权都要走一遍):
1. 首次使用 → 弹窗 → 允许 → 功能正常
2. 首次使用 → 弹窗 → 拒绝 → 是否有友好提示 + 能否重新唤起
3. 拒绝后再次点击 → 是否能再次弹窗(或引导去设置页)
4. 系统层面关闭权限(手机设置里关)→ 小程序内是否有提示并引导
5. 已授权 → 卸载微信重装 / 换设备登录 → 授权状态是否同步
6. 授权弹窗期间切后台再回来 → 不会卡死
💡 “拒绝后不能再弹出”是经典问题:微信的授权弹窗用户拒绝后,短时间内再调不会再弹,需要开发做引导到设置页(
wx.openSetting)的处理。
3.4 支付测试(微信支付,重点)
流程:下单(服务端统一下单)→ 拿到 timeStamp/nonceStr/package/signType/paySign → wx.requestPayment → 输入密码 → 支付结果回调 → 服务端查单确认 → 更新订单状态
测试矩阵:
| 场景 | 预期 |
|---|---|
| 正常支付成功 | 订单变已支付,支付记录生成 |
| 支付中取消 | 订单仍为待支付,可重新发起(不能生成重复订单) |
| 余额不足/密码错误 | 明确提示,订单状态不变 |
| 支付成功但网络中断 | 以服务端查单结果为准(不能只信客户端回调) |
| 快速点两次支付 | 只能付一次(幂等) |
| 支付后返回按钮 | navigateBack 回到的页面状态正确 |
| 退款 | 全额/部分退款,金额与状态正确 |
| 金额篡改 | 抓包改金额 → 服务端必须重新计算(见安全测试篇) |
| 小额验证 | 0.01 元、超大金额、负数 |
⚠️ 重点:微信支付回调是异步的,客户端
success只代表微信侧成功,订单状态必须以服务端查单为准。测试方法:支付后立即断网,看订单最终是否变为已支付。
3.5 分享与转发
| 能力 | API | 测试点 |
|---|---|---|
| 转发给好友/群 | onShareAppMessage |
标题、图片、path 参数、自定义按钮转发 |
| 分享到朋友圈 | onShareTimeline |
单页模式(无登录态、部分能力不可用★) |
| 生成小程序码/二维码 | 服务端 wxacode.get / getUnlimited |
scene 参数解析(getUnlimited 的 scene 最长 32 字符) |
| 分享后数据统计 | 后台”分享”埋点 | 分享次数、回流率 |
⚠️ 朋友圈单页模式是高频坑:从朋友圈打开时是”单页模式”,不支持登录态、不支持跳转其他页面、部分组件不可用。必须单独测这条路径,否则用户从朋友圈进来看到的是空白或报错。
3.6 订阅消息
| 类型 | 说明 |
|---|---|
| 一次性订阅 | 用户每授权一次可发一条(可勾选”总是保持以上选择”) |
| 长期订阅 | 仅政务民生等特定行业 |
测试点:
- 授权弹窗文案与实际发送的消息一致
- 用户拒绝后是否有降级方案(如站内消息)
- 模板 ID 与模板关键词是否匹配(关键词类型有长度限制)
- 消息下发时机是否正确(支付后、审核后…)
- 内容含敏感词/超长会被拦截
3.7 交互与中断测试
□ 下拉刷新(onPullDownRefresh)—— 需配置 enablePullDownRefresh
□ 上拉触底加载(onReachBottom)—— 无更多数据的提示、重复触发
□ 页面滚动(onPageScroll)
□ 切后台再回来(onShow)—— 数据刷新、定时器、音视频暂停
□ 来电/短信/微信电话中断
□ 锁屏解锁
□ 微信被系统杀掉后重进
□ 弱网/断网(见 4.4)
□ 微信内其他小程序来回切换
□ 下拉"最近使用"/"我的小程序"收藏后进入
□ 系统字体放大(微信 → 我 → 设置 → 通用 → 字体大小)
□ 深色模式(DarkMode)
3.8 数据缓存(Storage)
wx.setStorageSync('key', value) // 同步
wx.setStorage({ key, data }) // 异步
wx.getStorageSync('key')
wx.removeStorageSync('key')
wx.clearStorage()
限制与测试点:
| 项 | 说明 |
|---|---|
| 容量 | 单个小程序约 10MB(以官方为准) |
| 隔离 | 按 用户 + 小程序 维度隔离(换账号数据不共享) |
| 清理 | 微信可能主动清理(长时间未使用、空间不足) |
| 测试点 | 缓存失效后是否有兜底;退出登录后缓存是否清除;换账号是否串数据 |
💡 高频 Bug:退出登录后只清了 token,没清业务缓存 → 下一个账号看到上一个账号的数据(信息安全问题)。
3.9 分包与更新
主包 ≤ 2MB,整包 ≤ 20MB(以官方文档为准,不同时期有调整)
分包:subPackages 配置,可按需加载
测试点:
□ 首次进分包页是否有加载提示(不能白屏)
□ 分包预下载规则(preloadRule)是否生效
□ 分包大小超限时的表现
□ 版本更新:wx.getUpdateManager()
· 新版本发布后,老用户冷启动是否收到更新提示
· 强制更新 / 静默更新 的行为是否符合预期
· 更新后本地缓存数据是否兼容(旧数据结构)
四、性能测试
4.1 体验评分(Audits)
开发者工具 → 体验评分 / Audits → 自动跑分,给出问题与优化建议。
官方建议值(参考):
| 指标 | 建议 |
|---|---|
| 首屏渲染时间 | ≤ 5s |
| 渲染时间 | ≤ 500ms |
| 脚本执行时间 | ≤ 1s |
setData 单次数据 |
< 256KB(建议 < 64KB) |
| 页面节点数 | < 1000(建议 < 500) |
| 图片大小 | > 100KB 建议压缩 |
| 网络请求耗时 | < 1s |
| WXML 节点层级 | < 30 层 |
4.2 setData 优化(小程序性能第一杀手)
// ❌ 错误:频繁调用
this.setData({ count: 1 });
this.setData({ name: 'a' });
// ✅ 正确:合并
this.setData({ count: 1, name: 'a' });
// ❌ 错误:传整个大对象
this.setData({ list: this.data.list });
// ✅ 正确:只传变化的部分(路径写法)
this.setData({ 'list[0].name': 'new' });
// ❌ 错误:后台页面还在 setData
// ✅ 正确:onHide 时停止数据刷新与定时器
测试方法:
- 开发者工具的 Trace / Performance 面板,看
setData耗时与频率 - 真机上用 PerfDog 或微信自带的性能面板
- 长列表快速滑动,观察是否卡顿(FPS < 50 即为不流畅)
4.3 启动性能
| 类型 | 定义 |
|---|---|
| 冷启动 | 首次打开 / 被销毁后重新打开(含代码包下载) |
| 热启动 | 切后台 5 分钟内再打开 |
测试点:
- 冷启动耗时(目标 ≤ 3s,含首屏内容可见)
- 首屏是否有骨架屏/loading,而非白屏
- 热启动是否恢复到之前的页面(而非回首页)
- 启动时的网络请求数是否合理(不要串行依赖太多)
4.4 弱网与网络测试
| 场景 | 预期 |
|---|---|
| 断网 | 友好提示 + 重试入口(不能白屏/卡死) |
| 弱网(2G/高延迟) | loading 状态、超时处理 |
| 网络切换(WiFi ↔ 4G) | 请求不中断、能重试 |
| 重复提交 | 弱网点两次提交按钮 → 不能产生双订单 ★ |
| 接口超时 | 有超时时间(默认 60s,建议设更短) |
💡 弱网模拟用 Charles 的 Throttle,详见 抓包工具 篇。真机弱网也可用 QNET、弱网王等工具。
4.5 内存与稳定性
- 长时间使用内存是否持续增长(泄漏)
- 快速反复进出某页面,是否累积内存
- 长列表无限滚动(几万条)是否崩溃
- 图片列表加载大量大图是否 OOM
- 后台切换 50 次是否稳定
稳定性压测思路可参考 Monkey稳定性测试(小程序需借助微信内的随机操作或自研脚本)。
五、兼容性测试
5.1 兼容矩阵
| 维度 | 覆盖范围 |
|---|---|
| 微信版本 | 近 2 年主流版本(微信客户端决定基础库) |
| 基础库版本 | ★ 后台可设置”最低基础库版本”,低于该版本的微信会提示升级 |
| 操作系统 | iOS(近 3 个大版本)、Android(8/9/10/11/12/13+) |
| 机型 | 主流厂商(华米 OV、荣耀)、低端机、折叠屏、平板 |
| 屏幕 | 刘海屏、挖孔屏、水滴屏、小屏(iPhone SE)、大屏 |
| 深色模式 | iOS / Android 深色模式 |
| 字体大小 | 微信内设置为最大 |
⚠️ 基础库是小程序兼容的核心变量:新 API 在低基础库上不存在,直接调用会报错。测试方法:开发者工具 → 详情 → 本地设置 → 调低调试基础库版本,逐个验证。
5.2 屏幕适配
单位:rpx(750rpx = 屏幕宽度,自动适配)
安全区:env(safe-area-inset-bottom) ← 底部操作栏必测(iPhone 全面屏小黑条)
测试点:
□ iPhone 全面屏底部按钮是否被小黑条遮挡
□ 刘海屏顶部导航栏是否重叠
□ 横屏 / 平板(部分小程序横屏布局错乱)
□ 折叠屏展开/折叠时布局是否刷新
□ 小屏机型文字是否溢出、按钮是否可点(最小点击区 44px)
六、自动化测试方案
6.1 方案对比
| 方案 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| Minium(官方)★ | Python,控制开发者工具或真机 | 官方支持、能跨自定义组件、支持真机 | 需装开发者工具,环境略重 |
| Appium | 切 WebView context 操作 | 可与原生 App 混合测试 | 小程序 WebView 定位不稳定 |
| Airtest / Poco | 图像识别 + UI 树 | 对 canvas、游戏类小程序有效 | 图像识别维护成本高 |
| 接口自动化 | pytest + requests 打服务端接口 | 稳定、快 | 覆盖不到页面 |
| 开发者工具 CLI | 命令行控制工具(预览/上传/自动化端口) | 适合 CI | 需配合框架使用 |
💡 推荐组合:接口自动化(覆盖 70%)+ Minium(覆盖核心页面流程)+ 手工专项(兼容/支付/授权)。这是投入产出比最高的搭配。
6.2 Minium 环境搭建
# 1. 安装(Python 3.8+)
pip install minium
# 2. 微信开发者工具 → 设置 → 安全 → 打开"服务端口"
# 3. 验证
minitest --help
配置文件 config.json:
{
"project_path": "/Users/you/project/miniprogram",
"dev_tool_path": "/Applications/wechatwebdevtools.app/Contents/MacOS/cli",
"platform": "ide",
"debug_mode": "info",
"enable_network_panel": true,
"report_usage": true
}
| 字段 | 说明 |
|---|---|
project_path |
小程序项目根目录 |
dev_tool_path |
开发者工具 CLI 路径(Windows 用 cli.bat 路径) |
platform |
ide(模拟器)/ Android / iOS(真机) |
debug_mode |
info / debug / warn / error |
6.3 Minium 第一个用例
# test_login.py
import minium
class TestLogin(minium.MiniTest):
"""继承 MiniTest,即可用 unittest 的全部断言"""
def test_login_success(self):
# 1. 跳转页面
self.app.navigate_to("/pages/login/index")
# 2. 定位元素并操作
self.page.get_element("#username").input("testuser")
self.page.get_element("#password").input("123456")
# 3. 点击
self.page.get_element(".login-btn").click()
# 4. 等待并断言
self.page.wait_for(".user-info", max_timeout=10)
nickname = self.page.get_element(".nickname").inner_text
self.assertIn("testuser", nickname)
def test_login_empty_password(self):
self.app.navigate_to("/pages/login/index")
self.page.get_element("#username").input("testuser")
self.page.get_element(".login-btn").click()
# 断言错误提示出现
self.assertTrue(self.page.wait_for(".error-tip", max_timeout=3))
执行:
# 跑单个文件
minitest -m test_login.py -c config.json
# 跑整个目录并生成报告 ★
minitest -m ./testcase -c config.json --generate-report
# 只跑某个用例
minitest -m test_login.py -c config.json --case TestLogin.test_login_success
6.4 元素定位
| 选择器 | 示例 | 说明 |
|---|---|---|
| ID | #username |
|
| Class | .login-btn |
|
| 标签 | view、button |
|
| 层级 | .container .list .item |
|
| 跨自定义组件 | .page >>> .custom-comp .btn |
★ >>> 穿透自定义组件 |
| 按文本 | get_element("button", inner_text="登录") |
|
| 文本包含 | get_element("view", text_contains="成功") |
|
| 多元素 | page.get_elements(".item") |
返回列表 |
# 常用元素操作
el = self.page.get_element("#input")
el.input("文本") # 输入
el.click() # 点击
el.clear() # 清空
el.inner_text # 文本
el.attribute("class") # 属性
el.get_style("color") # 样式
# 页面级操作
self.page.wait_for(".el", max_timeout=10) # 等待元素出现
self.page.wait_for_page("/pages/index/index") # 等待页面切换
self.page.data # 获取页面 data
self.page.scroll_to(300) # 滚动
self.page.get_element(".btn").trigger("tap") # 触发事件
# 应用级操作
self.app.navigate_to("/pages/x/index")
self.app.switch_tab("/pages/home/index")
self.app.navigate_back()
self.app.get_current_page()
self.app.get_page_stack() # 看页面栈(验证 10 层限制 ★)
⚠️ 原生组件(
video/map/canvas/camera/textarea):在部分模式下无法用普通选择器定位,需要用真机模式或特殊 API,测试脚本设计时要避开这些元素或用坐标点击。
6.5 PO 模式封装
# pages/login_page.py
import minium
class LoginPage:
"""登录页对象"""
def __init__(self, mini: minium.MiniTest):
self.mini = mini
def open(self):
self.mini.app.navigate_to("/pages/login/index")
self.mini.page.wait_for("#username")
return self
def login(self, username: str, password: str):
self.mini.page.get_element("#username").input(username)
self.mini.page.get_element("#password").input(password)
self.mini.page.get_element(".login-btn").click()
def get_error_tip(self) -> str:
el = self.mini.page.get_element(".error-tip")
return el.inner_text
def is_login_success(self) -> bool:
return self.mini.page.wait_for(".user-info", max_timeout=10)
# test_login_po.py
import minium
from pages.login_page import LoginPage
class TestLoginPO(minium.MiniTest):
def setUp(self):
self.login_page = LoginPage(self)
def test_login_ok(self):
self.login_page.open().login("testuser", "123456")
self.assertTrue(self.login_page.is_login_success())
def test_login_fail(self):
self.login_page.open().login("testuser", "wrong")
self.assertIn("密码错误", self.login_page.get_error_tip())
PO 模式的完整方法论见 PO模式。
6.6 数据驱动与失败截图
import minium
import pytest
class TestLoginDDT(minium.MiniTest):
# minium 基于 unittest,用 subTest 或参数化实现数据驱动
CASES = [
("testuser", "123456", True),
("testuser", "wrong", False),
("", "123456", False),
]
def test_login_cases(self):
for username, pwd, expect_ok in self.CASES:
with self.subTest(username=username):
self.app.navigate_to("/pages/login/index")
self.page.get_element("#username").input(username)
self.page.get_element("#password").input(pwd)
self.page.get_element(".login-btn").click()
actual = self.page.wait_for(".user-info", max_timeout=5)
self.assertEqual(expect_ok, actual)
def tearDown(self):
# 失败时截图,附到报告
if self._outcome and self._outcome.errors:
self.app.capture_screenshot(f"./screenshots/{self._testMethodName}.png")
super().tearDown()
6.7 接入 CI
# 开发者工具 CLI 的其他能力(可用于 CI)
cli --auto <project> --auto-port 9420 # 启动自动化端口
cli --preview <project> # 生成预览二维码
cli --upload <project> --upload-desc "v1.0" # 上传(生成体验版)
cli --build-npm <project> # 构建 npm
cli --login # 登录(需扫码)
# GitLab CI 示例(接口自动化 + 关键流程 UI)
stages:
- test
miniprogram-test:
stage: test
script:
- pip install minium pytest requests
- pytest tests/api/ -v # 接口自动化
- minitest -m ./testcase -c config.json --generate-report
artifacts:
when: always
paths:
- outputs/
七、抓包与接口测试
7.1 小程序的网络请求
wx.request({
url: 'https://api.example.com/order/list',
method: 'POST',
data: { page: 1 },
header: { 'content-type': 'application/json', 'token': 'xxx' },
success: (res) => { },
fail: (err) => { }
})
约束:
- 必须 HTTPS
- 域名必须在后台配置 request 合法域名
- 不能有端口、不能用 IP
- 并发上限 10 个(wx.request / uploadFile / downloadFile 各自限制)
7.2 抓包方法
| 环境 | 方法 |
|---|---|
| 开发者工具 | 调试器 → Network 直接看(最简单) |
| iOS 真机 | Charles 装证书 + 描述文件信任 |
| Android 真机 | Android 7+ 用户证书不信任 → 需 root 装系统证书,或用低版本 Android |
| 通用 | 开发者工具”真机调试”看 Network |
Charles 抓小程序步骤:
1. 手机 WiFi 代理指向电脑(同抓包工具篇)
2. 手机安装并信任 Charles 证书
iOS:设置 → 通用 → 关于本机 → 证书信任设置 → 打开开关 ★
Android 7+:用户证书对 App 不生效,需 root 或用 Android 6 及以下设备
3. Charles 开启 SSL Proxying,添加小程序域名
4. 手机上打开小程序,即可看到请求
详细步骤见 抓包工具 篇。小程序强制 HTTPS,所以证书这一步绕不开。
7.3 接口测试要点
- 合法域名:正式环境是否能正常请求(开发时勾了”不校验”,上线忘配会全挂)★
- 鉴权:不带 token / 过期 token / 他人 token(越权)
- 参数校验:服务端二次校验(金额、数量、状态)
- 返回数据脱敏:手机号、身份证
- 并发限制:小程序并发 10 个上限的表现
- 超时处理:接口慢时前端是否有 loading 与超时提示
安全测试要点见 安全测试 篇(越权、金额篡改、敏感信息)。
八、合规与审核(小程序特有)
提交审核前必须自查,被拒会拖慢上线:
| 常见被拒原因 | 自查项 |
|---|---|
| 功能不完整 | 提供了测试账号密码?体验版能正常跑通全流程? |
| 诱导分享/关注 | 是否有”分享后才能使用”“关注公众号才能领奖” |
| 虚拟支付 | iOS 端小程序不允许虚拟商品用微信支付(如充值会员、虚拟币) |
| 类目不符 | 小程序实际功能与所选类目一致?涉及特殊行业需资质(医疗/金融/教育) |
| 内容违规 | 敏感词、色情、政治、侵权内容 |
| 用户信息收集 | 是否有隐私协议?是否在收集前告知? |
| 未提供客服 | 是否配置了客服功能 |
| 名称/简介 | 含违规词、与实际不符、侵犯他人商标 |
💡 测试同学要做的:在”提审前”用体验版完整走一遍新用户全流程(注册 → 授权 → 主流程 → 支付),确保审核人员按默认路径能跑通。
九、常见问题速查
| 问题 | 原因 | 解决 |
|---|---|---|
| 扫体验版二维码提示”无权限” | 不是体验成员 | 让管理员在后台”成员管理”添加 |
| 真机白屏 | 域名未配合法域名 / 代码报错 | 看 vConsole 日志;检查后台域名配置 |
| 开发者工具能跑,真机不行 | 证书/域名/基础库差异 | 真机调试看日志 |
| 分享打开跳首页 | path 未带参数或参数解析错 | 检查 onShareAppMessage 的 path |
| 从子页返回数据不刷新 | 逻辑写在 onLoad |
应写在 onShow |
| 连续跳转后点不动 | 页面栈满 10 层 | 用 redirectTo 或 reLaunch |
| 授权弹窗不再出现 | 微信限制,拒绝后短时间内不弹 | 引导 wx.openSetting |
| 支付后订单未更新 | 只信了客户端回调 | 服务端主动查单 |
| iOS 无法支付 | 虚拟商品 iOS 不支持微信支付 | 改为实体商品或用其他方式 |
| 抓不到 HTTPS 包 | Android 7+ 证书限制 | root 装系统证书 / 换低版本设备 |
| 元素定位不到自定义组件内的元素 | 未穿透 | 用 >>> 选择器 |
| 原生组件无法点击 | video/map 层级最高 | 真机模式或坐标点击 |
| 更新后老用户看到旧版 | 未处理更新逻辑 | 用 wx.getUpdateManager() |
十、测试 Checklist(可直接用)
基础功能
□ 首次打开 / 冷启动 / 热启动
□ 各入口进入(扫码、分享、公众号、搜索、下拉、朋友圈)
□ 页面跳转与返回、页面栈上限
□ 授权(首次允许 / 拒绝 / 拒绝后重试 / 系统层关闭)
□ 登录态(过期、换账号、退出登录清缓存)
业务
□ 主流程全流程跑通
□ 表单校验(必填、长度、类型、边界)
□ 列表(空、单条、大量、分页、无更多)
□ 支付(成功、取消、失败、重复提交、退款)
□ 分享(标题、图片、参数、朋友圈单页模式)
□ 订阅消息(授权、下发时机、内容)
非功能
□ 弱网/断网/超时
□ 中断(来电、切后台、锁屏)
□ 兼容(微信版本、基础库、机型、系统、深色模式、字体)
□ 性能(启动耗时、setData、FPS、内存)
□ 安全(越权、金额篡改、敏感信息脱敏、HTTPS)
发布前
□ 体验版全流程验证
□ 合法域名配置正确
□ devMode/调试开关关闭
□ 审核规范自查
□ 版本号、更新逻辑
十一、学习资源
| 资源 | 说明 |
|---|---|
| 微信小程序官方文档 | 框架、组件、API 权威文档 |
| Minium 官方文档 | 小程序自动化测试框架 |
| 小程序运营规范 | 审核规范,提审前必读 |
| 小程序性能优化指南 | 官方性能建议 |
| 场景值列表 | 全部 scene 值 |
| 微信开发者工具下载 | 含 CLI 说明 |
| PerfDog | 真机性能采集(腾讯出品) |
| 抓包工具 | 本站:Charles/弱网 |
| ADB与移动端专项 | 本站:真机与性能 |
| 安全测试 | 本站:越权与业务安全 |