【测试】移动APP测试

文章目录

  • 移动APP测试
    • 一、APP的测试点
    • 二、功能测试:不值是把页面点一遍
      • [2.1 四种核心测试设计方法](#2.1 四种核心测试设计方法)
        • [2.1.1 等价类划分](#2.1.1 等价类划分)
        • [2.1.2 边界值分析](#2.1.2 边界值分析)
        • [2.1.3 场景法](#2.1.3 场景法)
        • [2.1.4 错误推测法](#2.1.4 错误推测法)
      • [2.2 登录模块完整用例(示例)](#2.2 登录模块完整用例(示例))
      • [2.3 APP功能测试和Web功能测试的核心区别](#2.3 APP功能测试和Web功能测试的核心区别)
      • [2.4 APP测试和小程序测试的核心区别](#2.4 APP测试和小程序测试的核心区别)
    • 三、兼容性测试:APP测试最重的板块
      • [3.1 Android碎片化](#3.1 Android碎片化)
      • [3.2 品牌ROM的测试注意事项](#3.2 品牌ROM的测试注意事项)
      • [3.3 屏幕适配测试](#3.3 屏幕适配测试)
      • [3.4 输入法兼容性](#3.4 输入法兼容性)
    • 四、专项测试:APP测试的"独门绝活"
      • [4.1 弱网测试](#4.1 弱网测试)
      • [4.2 中断测试](#4.2 中断测试)
        • [4.2.1 来电中断](#4.2.1 来电中断)
        • [4.2.2 切换后台](#4.2.2 切换后台)
        • [4.2.3 系统弹窗和事件](#4.2.3 系统弹窗和事件)
        • [4.2.4 Android 返回键 以及 iOS 手势返回](#4.2.4 Android 返回键 以及 iOS 手势返回)
      • [4.3 耗电量测试](#4.3 耗电量测试)
      • [4.4 流量消耗测试](#4.4 流量消耗测试)
      • [4.5 安装 / 卸载 / 升级测试](#4.5 安装 / 卸载 / 升级测试)
    • 五、性能测试
      • [5.1 响应时间基准](#5.1 响应时间基准)
      • [5.2 内存测试](#5.2 内存测试)
      • [5.3 CPU测试](#5.3 CPU测试)
      • [5.4 后端接口压力测试(JMeter)](#5.4 后端接口压力测试(JMeter))
    • 六、安全测试
      • [6.1 数据存储安全](#6.1 数据存储安全)
      • [6.2 数据传输安全](#6.2 数据传输安全)
      • [6.3 权限与越权](#6.3 权限与越权)
      • [6.4 反编译与代码安全](#6.4 反编译与代码安全)
    • 七、UI自动化测试
      • [7.1 Appium:跨平台UI自动化](#7.1 Appium:跨平台UI自动化)
      • [7.2 元素定位方式](#7.2 元素定位方式)
      • [7.3 Page Object 模式](#7.3 Page Object 模式)
    • 八、APP测试检查清单

移动APP测试

一、APP的测试点

做APP测试最容易犯的错就是只测功能------把页面点一遍没崩就觉得测完了。但实际上功能测试只占APP测试工作量的50%左右,另一半是各种专项测试

复制代码
APP测试全景
│
├── 功能测试(50%)
│   ├── 正向流程:正常用户操作路径
│   ├── 异常流程:错误输入、异常操作
│   ├── 边界值:输入极限值
│   └── 权限:首次授予、拒绝、二次触发
│
├── 兼容性测试(15%)
│   ├── 系统版本:Android 10-15、iOS 15-18
│   ├── 手机品牌:华为/小米/OPPO/vivo/三星
│   ├── 屏幕尺寸:小屏/主流/大屏/折叠屏
│   └── 网络环境:WiFi/4G/5G/弱网
│
├── 专项测试(20%)
│   ├── 弱网测试:2G/3G/4G/弱WiFi/断网/网络切换
│   ├── 中断测试:来电/短信/闹钟/锁屏/低电量/后台
│   ├── 耗电测试:后台播放/持续定位/高频网络请求
│   ├── 流量测试:首次启动/页面浏览/流媒体播放
│   └── 安装升级测试:首次安装/覆盖/升级/降级/卸载重装
│
├── 性能测试(10%)
│   ├── 响应时间:冷启动/热启动/页面切换/接口
│   ├── 内存:内存占用/内存泄漏/低内存回收
│   ├── CPU:空闲/正常/峰值
│   ├── 帧率:滑动流畅度/动画卡顿
│   └── 并发:多用户同时操作的稳定性
│
└── 安全测试(5%)
    ├── 数据存储:密码/Token/数据库文件
    ├── 数据传输:HTTPS/证书校验/加密
    ├── 权限控制:横向越权/纵向越权
    └── 反编译:APK/IPA代码安全

二、功能测试:不值是把页面点一遍

2.1 四种核心测试设计方法

2.1.1 等价类划分

案例:手机号输入框

等价类 代表值 是否有效
有效11位,1开头 13800138000 有效
有效11位,非1开头(虚拟运营商) 17012345678 有效(取决于产品规则)
少于11位 138001 无效
多于11位 138001380001 无效
含字母 138001abc00 无效
含特殊符号 138-0013-8000 视产品规则
空值 (不输入) 无效
已注册手机号 已注册的真实号 有效(登录场景)
未注册手机号 未注册的新号 无效(登录场景)/ 有效(注册场景)
2.1.2 边界值分析

边界是bug的高发地带,取边界值本身和紧邻的两个值。

案例:验证码倒计时60秒

时刻 操作 预期
刚点击"获取验证码" 立刻再点击 按钮置灰,不可点
第1秒 点击 不可点
第59秒 点击 不可点
第60秒 点击 重新变为可点击
第61秒 点击 可点

同样,输入框的 maxlength=200:用199/200/201个字符各测一次。

2.1.3 场景法

模拟用户从打开APP到完成目标的完整操作路径。

案例:爱听外语"从扫码到完成一篇精听"

用场景法测试时关注:步骤间的数据传递是否一致(比如音频下载后的缓存路径、听写进度的保存和恢复)。

2.1.4 错误推测法

靠经验猜"这个地方最容易出bug"然后针对性验证。常见的直觉测试点:

  • 网络切换时提交表单
  • 快速连续点击同一个按钮
  • 输入内容很多后再删完
  • 跨天/跨月的连续操作
  • 两个功能同时进行(如下载的同时播放音频)

2.2 登录模块完整用例(示例)

以爱听外语APP登录页面为例,按照功能测试的维度展开:

手机号输入

场景 输入 预期
正常 13800138000 格式校验通过
空值 (空) 提示"请输入手机号"
非11位 13800 提示"请输入正确的手机号"
含字母 138001abc00 提示"请输入正确的手机号"
含空格 138 0013 8000 自动过滤空格或提示格式错误
含emoji 138001😀8000 自动过滤
SQL注入 ' OR 1=1 -- 被拦截或视为无效输入

获取验证码

场景 操作 预期
正常发送 手机号正确,点获取 收到短信,倒计时开始
60秒内 倒计时中再次点击 按钮置灰不可点
重复获取 1分钟内同一手机号 频率限制,提示稍后再试
断网 无网络时点击 提示"网络连接失败"
服务端错误 服务端返回500 提示"服务异常,请稍后重试"
短信延迟 60秒后才收到 验证码可能已过期

协议勾选

场景 操作 预期
都不勾 直接点登录 提示"请先同意用户协议和隐私政策"
只勾一个 勾用户协议不勾隐私政策点登录 提示或登录按钮不可用
勾选再取消 两个都勾后取消一个 登录按钮变回不可用
点击协议链接 点击《用户协议》文字 跳转到协议详情页

2.3 APP功能测试和Web功能测试的核心区别

维度 APP Web
输入方式 软键盘(不同输入法)+ 物理按键 物理键盘为主
手势操作 左滑删除/下拉刷新/长按菜单/双击放大 鼠标点击/滚轮
屏幕方向 横屏竖屏切换 窗口大小调整
返回行为 物理返回键/手势返回(Android)vs 左上角返回(iOS) 浏览器返回按钮
多任务 分屏/悬浮窗模式 多标签页

2.4 APP测试和小程序测试的核心区别

维度 原生APP 微信小程序
运行环境 独立运行在操作系统之上 依赖微信客户端(WebView + JsCore 双线程)
安装方式 应用商店下载安装(几十MB~几GB) 无需安装,扫码即用(包体 ≤ 20MB)
系统权限 独立申请系统权限,弹窗样式各ROM不同 继承微信权限体系,弹窗统一
兼容矩阵 系统版本 × 手机品牌 × 屏幕尺寸 + 微信版本 × 基础库版本
发布更新 应用商店审核1-3天,用户手动更新 审核通过即时生效,用户无感
后台行为 受各ROM后台策略影响(华为激进/原生宽松) 受微信后台策略统一管控
页面栈 无限制,Activity/Fragment自由管理 最多10层,超出后 navigaTo 失效
包体积 无严格限制(通常数百MB) 主包 ≤ 2MB,总包 ≤ 20MB(含所有分包)
自动化工具 Appium / UIautomator2 / XCUITest minium / Airtest / 微信云测
抓包调试 Charles/Fiddler 直接抓 需额外配置(Android需root或VirtualXposed)
调试工具 Android Studio / Xcode 微信开发者工具(模拟器 + 真机调试)
代码安全 APK可被jadx反编译,IPA可被class-dump解包 wxapkg可被解包,核心逻辑必须放后端
支付体系 接入各平台支付SDK(支付宝/微信/银联) 仅支持微信支付,走 wx.requestPayment
缓存上限 自由管理空间 Storage API 上限 10MB
登录方式 手机号/第三方/生物识别 微信一键登录 + 手机号授权 + 第三方
测试策略差异 专项测试重:弱网/中断/耗电/流量/安装升级 专项测试轻(微信托管大部分),但需额外验证包体积和基础库兼容

三、兼容性测试:APP测试最重的板块

3.1 Android碎片化

兼容维度 最小覆盖 理想覆盖
Android系统版本 10/11/12/13/14/15 (6个) 最小覆盖 + 各版本的不同ROM
手机品牌 华为/小米/OPPO/vivo/三星 (5个) 前5 + 荣耀/一加/realme/中兴
屏幕分辨率 720p/1080p/2K (3个) 常见DPI组合全覆盖
iOS系统版本 15/16/17/18 (4个) 覆盖所有仍在支持的版本
屏幕类型 直面屏/曲面屏/折叠屏 每种形态全覆盖

理想情况下兼容性测试量 = 6 × 5 × 3 ≈ 90个环境。实际不可能全手工覆盖,通常策略是:

  • 手工测试:覆盖Top 5品牌 × 最新2个系统版本 = 10台真机
  • 云测平台:Testin、WeTest等云端覆盖剩余组合
  • 灰度发布:先1%用户 → 再10% → 全量

3.2 品牌ROM的测试注意事项

品牌 ROM 定制深度 测试注意点
华为 HarmonyOS/EMUI 极深 后台进程管理极激进,APP易被杀;推送走华为通道
小米 HyperOS/MIUI 权限弹窗文案和原生不同;省电模式限制后台;小窗模式
OPPO ColorOS 通知权限默认关闭;应用自启动需手动开启
vivo OriginOS 悬浮窗权限逻辑不同;后台弹窗受限
三星 OneUI 较接近原生Android;折叠屏适配重点机型
荣耀 MagicOS 与华为分家后推送/权限体系独立
Pixel 原生Android 作为基准参照

测试必须验证的场景

  • APP被系统杀进程后,重新打开的状态(数据是否丢失、登录态是否还在)
  • 首次安装时权限弹窗的样式(不同ROM弹窗文案和按钮位置不同)
  • 后台播放音频是否受限(华为/小米比较激进,可能在锁屏后几分钟杀掉)

3.3 屏幕适配测试

尺寸分类

类别 典型分辨率 测试要点
小屏 720×1280 (4.7-5.5寸) 内容是否截断,按钮是否过小无法点击
主流 1080×1920/1080×2400 (6.1-6.7寸) 首选测试基准
大屏 1440×2560/1440×3200 (6.8寸+) 字体缩放后是否溢出
平板 2048×1536 等 横屏布局是否合理
折叠屏 展开/折叠状态 状态切换时布局是否自适应

全面屏适配

适配项 测试方法
挖孔/刘海区域 查看APP内容是否被遮挡
底部指示条区域 底部按钮是否被虚拟Home指示条遮挡
全面屏手势 侧滑返回手势是否和APP内滑动冲突
状态栏沉浸 顶部状态栏和APP导航栏颜色是否协调

3.4 输入法兼容性

不同第三方输入法会影响键盘弹出行为和输入框位置:

输入法 测试注意
搜狗输入法 市场占有率最高,必测
百度输入法 自定义工具栏可能遮挡输入框
讯飞输入法 语音输入模式切换
系统自带 三星键盘/华为小艺输入法/iOS原生键盘
第三方键盘(iOS) iOS 支持第三方键盘但行为可能不一致

核心测试点:键盘弹出时页面是否能滚动到输入框可见的位置,键盘收起后页面是否能恢复。

四、专项测试:APP测试的"独门绝活"

4.1 弱网测试

用户在电梯、地铁、地下车库使用APP是常态,弱网下的表现直接影响留存

模拟工具

  • Charles Proxy:Proxy → Throttle Settings → 配置限速参数
  • Fiddler:Rules → Performance → Simulate Modem Speeds
  • iOS 开发者模式:设置 → 开发者 → Network Link Conditioner
  • Android 开发者模式:网络 → 选择网络类型

标准模拟参数

网络类型 上行 下行 延迟 丢包率 模拟场景
2G(GPRS) 20kbps 50kbps 500ms 5% 极限弱信号
弱3G 64kbps 192kbps 300ms 3% 偏远地区
强3G 128kbps 384kbps 200ms 1% 城郊
4G弱信号 1Mbps 5Mbps 100ms 1% 商场/地铁
4G强信号 10Mbps 40Mbps 40ms 0% 室外基站附近
弱WiFi 256kbps 512kbps 300ms 5% 远距离WiFi
网络抖动 正常 正常 0-1000ms波动 随机3% 高铁/高速移动
100%丢包 --- --- --- 100% 隧道/电梯

每种网络下的验证清单

复制代码
 页面是否能加载出来(可以慢但不能白屏死等)
 Loading状态是否明确展示(不能让用户以为卡死了)
 超时后是否给出提示(不能一直转圈)
 弱网下重复点击是否产生重复请求
 弱网下提交表单是否产生重复数据
 弱网切正常网络后是否能自动恢复(不需要用户重试)
 音视频播放:缓冲策略是否正确(不是一直加载0%)

网络切换测试

切换场景 测试方法 验证点
WiFi → 4G 播放中关WiFi 播放不中断或短暂缓冲后继续
4G → WiFi 连上WiFi 自动切换到更好的网络
4G → 飞行模式 打开飞行模式 暂停并提示网络不可用
飞行模式 → 4G 关闭飞行模式 自动恢复或手动可重试
WiFi→4G切换中提交 切换瞬间提交请求 请求不丢失,有重试机制

4.2 中断测试

APP在运行中会遇到各种系统级中断,每一个都必须验证:

4.2.1 来电中断
场景 APP状态 中断后表现 恢复后表现
登录/注册 填写表单中 通话界面覆盖APP 切回后表单数据保留
下单支付 支付中 APP退到后台 切回后查询支付结果
音视频播放 播放中 播放自动暂停 通话结束后可继续播放或需手动恢复
下载/上传 传输中 传输暂停 通话结束后自动续传
游戏/计时 计时中 计时暂停 通话结束后计时继续
4.2.2 切换后台
测试参数 说明
切后台时长 1分钟 / 5分钟 / 30分钟 / 2小时
切后台前APP状态 首页 / 填写表单 / 播放中 / 下单中
切回后验证 状态是否保持 / Token是否过期 / 数据是否同步

Android 和 iOS 差异

  • iOS "退到后台"3分钟后 APP 可能被系统冻结(Suspended状态),30分钟后可能被杀
  • Android 取决于 ROM 的进程管理策略,华为比原生 Android 激进得多
4.2.3 系统弹窗和事件
事件 测试方法 关键验证
低电量弹窗(20%/10%) 将手机用到临界电量 弹窗不导致APP崩溃
系统权限弹窗 触发权限 + 系统弹窗叠加 弹窗顺序正确
闹钟响起 设闹钟 + 使用APP 闹钟不导致APP卡死
日历提醒 设日程提醒 提醒弹窗不阻塞操作
短信通知 发短信给自己 顶部通知条不遮挡操作区
蓝牙连接提示 打开关闭蓝牙 如有蓝牙依赖功能验证状态变化
4.2.4 Android 返回键 以及 iOS 手势返回
平台 行为 测试要点
Android 物理/虚拟返回键 首页按返回 → 弹出退出确认或退回桌面
Android 物理/虚拟返回键 非首页 → 返回上一页,行为等同于navigateBack
iOS 左侧边缘右滑 仅在支持手势返回的页面生效
iOS 左上角返回按钮 所有子页面必须有,否则用户"卡住"

4.3 耗电量测试

音频类、视频类、定位类APP尤其需要关注耗电。

测试工具

平台 工具 用途
Android Battery Historian(Google官方) 精确到每个APP每个wakeLock的耗电
Android 开发者选项 → 正在运行的服务 简单查看
iOS Xcode → Debug → Energy Log 精细耗电分析
iOS 设置 → 电池 按APP查看耗电占比

测试场景与指标

场景 操作 合格标准
后台静置 APP在后台1小时 耗电 < 5%
在线音频播放 连续播放1小时 耗电 < 15%
GPS持续定位 持续定位1小时 耗电 < 25%
前台无操作 亮屏不操作10分钟 APP 耗电占比 < 5%

常见的耗电元凶

原因 表现 排查方法
持有WakeLock 屏幕关了CPU还在跑 Battery Historian
GPS未及时关闭 定位图标一直显示 查看状态栏定位图标
高频轮询 每秒请求一次接口 抓包看请求频率
动画未暂停 切后台后动画还在跑 开发者选项 → GPU呈现模式
后台音频未释放 退出播放后audio仍在 查看系统音频焦点

4.4 流量消耗测试

用户对流量消耗很敏感,尤其在非WiFi环境的下

测试工具

平台 工具
Android 设置 → 网络和互联网 → 数据使用量(可按APP筛选)
iOS 设置 → 蜂窝网络 → 查看各APP用量
Charles 统计请求总字节数

关键场景的流量基准

场景 合格 优秀
首次安装冷启动(含必要资源下载) < 5MB < 2MB
浏览一个列表页(20条数据) < 500KB < 200KB
浏览一个详情页(含图片) < 1MB < 300KB
音频流播放 10分钟 < 15MB < 10MB
后台1小时(无主动使用) < 1MB < 200KB

流量优化方向:图片懒加载、接口返回数据精简字段、缓存策略(列表数据10分钟内不重复请求)、WIFI下预加载大资源。

4.5 安装 / 卸载 / 升级测试

测试场景 具体操作 验证点
首次安装 应用商店下载 → 安装 → 首次打开 首次权限弹窗正常;引导页展示;无闪退
覆盖安装 同版本号APK再次安装 用户数据不丢失;不出现"安装失败
升级-数据迁移 v1.0 → v2.0(数据库表结构变了) 旧数据正确迁移到新表结构;新功能可用
升级-旧API兼容 v1.0 → v2.0(新API替代旧API) 检查是否仍有接口指向已废弃的旧API
跨版本大升级 v1.0 → v3.0 跨版本升级路径数据完整性
降级安装(Android) v2.0 → v1.0 应提示"无法降级"或数据回退处理
卸载 卸载APP APP所有文件被清除(不残留)
卸载重装 卸载 → 重新下载安装 干净安装;如果是登录用户,服务端数据仍保留
SD卡安装(Android) APK移到SD卡安装 安装和运行正常
外部存储迁移 应用设置中迁移到SD卡 迁移后功能正常

五、性能测试

5.1 响应时间基准

指标 合格 优秀 测试方法
冷启动 < 3秒 < 1.5秒 杀进程后手动计时
热启动 < 1秒 < 500ms 按Home后再打开
页面切换 < 500ms < 200ms 开发者选项 → GPU呈现模式
接口响应 < 1秒 < 300ms Charles 查看请求耗时
图片加载 < 2秒 < 1秒 弱网下降级对比
滑动帧率 > 55fps > 58fps 开发者选项 → 显示帧率

5.2 内存测试

测试工具

平台 工具
Android Android Studio Profiler / PerfDog / adb shell dumpsys meminfo
iOS Xcode Instruments / PerfDog

关键内存指标

APP类型 空闲内存 正常使用 高风险值
工具类APP < 80MB < 200MB > 300MB
音视频APP < 100MB < 300MB > 500MB
游戏APP < 200MB < 800MB > 1.2GB
大型3D游戏 < 500MB < 1.5GB > 2GB

内存泄漏检测

内存泄漏最直接的表现是:反复做同一操作,内存只升不降。

步骤

  1. 启动APP → 记录初始内存
  2. 反复执行目标操作20次(如反复打开关闭详情页)
  3. 返回首页 → 手动触发GC → 再次记录内存
  4. 如果内存明显高于初始值(高出30%以上),大概率存在泄漏

常见泄漏原因

原因 表现
静态变量持有Activity/Fragment引用 页面销毁后内存未释放
匿名内部类持有外部引用 Handler/Runnable未在onDestroy移除
单例持有Context 传入Activity的Context(应该用ApplicationContext)
资源未关闭 Cursor/InputStream/Bitmap 用完没关

5.3 CPU测试

测试工具

平台 工具
Android Android Studio Profiler / PerfDog / top命令
iOS Xcode Instruments
APP状态 CPU正常范围
前台空闲 < 5%
前台滚动列表 < 20%
前台播放音频 < 10%
前台复杂动画 < 30%(瞬时峰值可到50%)
后台 < 5%(不应持续占用CPU)

CPU异常场景:切到后台后CPU仍然高占用------可能在后台偷跑计算、动画未暂停、定时器未清除。

5.4 后端接口压力测试(JMeter)

后端性能和APP体验直接挂钩,用 JMeter 做后端压测:

第一:基准测试(单用户)

复制代码
线程数=1,循环=10次
目的:获取单用户下每个接口的响应时间基线

第二:负载测试(模拟日常峰值)

复制代码
线程数=50,Ramp-Up=10秒,持续5分钟
目的:模拟日常最高用户量的表现

第三:压力测试(找拐点)

轮次 并发数 持续时间 目的
1 100 5分钟 2倍负载
2 200 5分钟 4倍负载
3 500 5分钟 10倍负载,找拐点

第四:稳定性测试

复制代码
线程数=200,持续30分钟
目的:验证长时间运行是否有内存泄漏、连接池满等问题

JMeter核心监听器解读

指标 含义 参考标准
Average(平均响应时间) 所有请求的平均耗时 < 1秒
Median(中位数) 50%请求的耗时 < 800ms
90% Line 90%请求的耗时不超过此值 < 1.5秒
95% Line 95%请求的耗时不超过此值 < 2秒
Throughput(TPS) 每秒处理的事务数 越高越好
Error% 错误率 必须 < 1%

六、安全测试

6.1 数据存储安全

检测项 要求 测试方法
密码 不允许本地明文存储 检查 SharedPreferences/UserDefaults/keychain
Token 存储在 Keychain(iOS)/Keystore(Android) 检查存储位置是否为安全区域
数据库文件 SQLite DB 文件是否可被外部读取 root 手机进入 /data/data/包名/databases/ 查看
缓存文件 缓存中是否有敏感信息 检查 /cache 目录下的文件内容
日志文件 日志不打印Token/密码/手机号 查看 logcat 或控制台输出

Android 特别检查

复制代码
// 检查 SharedPreferences 是否存储敏感信息
adb shell
run-as com.example.app
cat shared_prefs/*.xml

// 检查 SQLite 数据库是否明文
cd databases
sqlite3 app.db
.tables
SELECT * FROM user;

6.2 数据传输安全

检测项 测试方法 处理
HTTPS强制 修改代码中的https为http,验证是否能发送 应被系统或框架拦截
证书校验 Charles代理抓包,安装Charles证书后验证APP是否仍然信任 应校验失败拒绝连接(SSL Pinning)
密码/验证码明文 抓包查看登录接口的请求体 密码应加密(至少base64,最好hash+salt)
Token有效期 拿到Token后修改系统时间或等待过期 过期后401,有刷新机制

6.3 权限与越权

检测项 测试方法
横向越权 用户A登录,修改请求中的userId为B的ID,查看B的数据
横向越权-订单 修改订单ID为其他用户的订单号
纵向越权 普通用户token请求管理员接口
未授权访问 不携带Token请求需要登录的接口
Token篡改 修改JWT Token中的payload部分(如把role从user改为admin)然后编码
支付金额篡改 抓包修改下单请求中的金额参数

6.4 反编译与代码安全

平台 反编译工具 防护建议
Android APK apktool/jadx/jeb 核心逻辑放服务端;代码混淆(ProGuard/R8);字符串加密
iOS IPA class-dump/Hopper Bitcode编译;代码混淆;关键字符串不要硬编码

七、UI自动化测试

7.1 Appium:跨平台UI自动化

Appium 是目前使用最广的移动端UI自动化框架,支持 iOS 和 Android。

架构原理

python 复制代码
from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# 连接设备
desired_caps = {
    "platformName": "Android",
    "platformVersion": "14",
    "deviceName": "Pixel 7",
    "appPackage": "com.aitingwaiyu.app",
    "appActivity": ".ui.login.LoginActivity",
    "noReset": True  # 不清除APP数据
}

driver = webdriver.Remote("http://localhost:4723/wd/hub", desired_caps)

# 等待元素并操作
wait = WebDriverWait(driver, 10)

phone_input = wait.until(
    EC.presence_of_element_located((AppiumBy.ID, "com.aitingwaiyu.app:id/et_phone"))
)
phone_input.send_keys("13800138000")

login_btn = driver.find_element(AppiumBy.ID, "com.aitingwaiyu.app:id/btn_login")
login_btn.click()

# 断言
toast = wait.until(
    EC.presence_of_element_located((AppiumBy.XPATH, "//android.widget.Toast"))
)
assert "请输入验证码" in toast.text

driver.quit()

7.2 元素定位方式

优先级 定位方式 示例 适用场景
1 accessibility id AppiumBy.ACCESSIBILITY_ID, "登录按钮" iOS/Android通用,最推荐
2 resource-id AppiumBy.ID, "com.xx:id/btn_login" Android专用
3 xpath AppiumBy.XPATH, "//android.widget.Button[@text='登录']" 兜底方案,最慢
4 class name AppiumBy.CLASS_NAME, "android.widget.EditText" 同类型元素多时不推荐
5 UIAutomator AppiumBy.ANDROID_UIAUTOMATOR, 'text("登录")' Android专用,比xpath快

7.3 Page Object 模式

python 复制代码
class LoginPage:
    """登录页面"""
    def __init__(self, driver):
        self.driver = driver
        self.phone_input = (AppiumBy.ID, "et_phone")
        self.code_btn = (AppiumBy.ID, "btn_get_code")
        self.login_btn = (AppiumBy.ID, "btn_login")

    def login(self, phone, code):
        self.driver.find_element(*self.phone_input).send_keys(phone)
        self.driver.find_element(*self.code_btn).click()
        # 输入验证码...
        self.driver.find_element(*self.login_btn).click()
        return HomePage(self.driver)


class HomePage:
    """首页"""
    def __init__(self, driver):
        self.driver = driver

    def get_user_name(self):
        return self.driver.find_element(AppiumBy.ID, "tv_user_name").text


# 用例
def test_login():
    login_page = LoginPage(driver)
    home_page = login_page.login("13800138000", "123456")
    assert home_page.get_user_name() == "测试用户"

八、APP测试检查清单

复制代码
功能测试
   正向流程:核心场景端到端走通
  异常流程:错误输入、异常操作
   边界值:输入极限值、临界时间点
   权限:首次授予/拒绝/二次触发/手改权限
   手势:左滑删除/下拉刷新/长按菜单/双击/侧滑返回

兼容性测试
   Android 10-15 系统版本
   iOS 15-18 系统版本
  华为/小米/OPPO/vivo/三星 各至少一台
  1080p 基准分辨率 + 720p + 2K
 折叠屏 + 平板 + 全面屏挖孔刘海
   输入法:搜狗/百度/系统自带

专项测试
   弱网:2G/3G/弱4G/弱WiFi/网络抖动/100%丢包
   网络切换:WiFi↔4G↔飞行模式
  中断:来电/短信/闹钟/低电量/后台/锁屏
   耗电:后台静置/在线播放/GPS定位 各1小时
   流量:首次启动/列表页/详情页/流媒体10分钟
   安装/升级/卸载/重装

性能测试
   冷启动 < 3秒
   反复操作无内存泄漏
   后台CPU < 5%
   滑动帧率 > 55fps
   后端接口90%Line < 1.5秒

安全测试
   全站HTTPS + 证书校验(SSL Pinning)
   Token存Keychain/Keystore
   横向越权 + 纵向越权
  密码/验证码加密传输
   日志无敏感信息打印