【测试】移动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
   横向越权 + 纵向越权
  密码/验证码加密传输
   日志无敏感信息打印