【腾讯 TMQ】专治时间长 —5 分钟测试 Android 覆盖安装
作者:TMQ 邓曦

一、痛点


覆盖安装测试,作为一项基本的测试类型是不可或缺的。它存在的主要价值:验证老版本覆盖升级到新版本,用户和系统数据能够正确迁移,以及保障用户升级后的功能可用性。

但是说他痛在什么地方呢?

二、解决方案

2.1 思路

从哲学上说,任何事物都是发展变化的。我们需要在 “变化” 中找寻 “不变” 的本质和规律。在覆盖安装过程中,我们也要找到 “不变” 的部分,那就是我们能够 “减少工作量” 的地方。

例如:某 APP1.0 版本覆盖升级到 APP2.0 版本。

在这个过程中哪些是不变的部分呢?

了解 Android 覆盖安装的同学都知道,覆盖安装后,APP1.0 版本的程序代码,完全更新为 APP2.0 版本的程序代码。但是,这种变化会在 “迭代” 测试中完全保证。因为 “迭代” 测试中 “全新安装” APP2.0 程序代码和 “覆盖安装 APP2.0 程序代码” 是相同的。

用户数据—用户使用 APP 过程中产生的数据。例如:用户使用 “浏览器” 打开了 www.qq.com, 那么浏览器访问历史中的 www.qq.com 就是用户数据。很显然,用户数据在覆盖升级的过程中不应该被改变。不仅如此,升级后的用户数据必须能够正常访问使用。这样才能保证用户在 APP 覆盖升级后使用的连贯与一致性。当然,这是理想的情况,在覆盖升级过程中用户数据也有可能发生变化。

很显然,(1)如果 “用户数据(不变部分)”,能够保证在覆盖升级后正常访问使用,这部分测试工作量就能被释放。(2)针对 “用户数据(变化部分)”,测试人员需要人工介入确认是否是问题。

现在的主要问题就变成了:如何保证 “用户数据(不变部分)” 的功能正确性?

【论据 1】APP1.0 覆盖升级为 APP2.0 后程序代码=全新安装 APP2.0 的程序代码。(成立)

【论据 2】APP2.0 在全新安装状态下,“迭代测试” 需要对主要功能进行 “地毯式” 的功能测试。只要使用 “用户数据(不变部分)” 作为测试数据,功能正确性就已经得到了保证。而在很多测试组,也确实就是这样做的。(成立)

【结论】“用户数据(不变部分)” 在覆盖升级后,不需要测试。(成立)

有了这个结论,我们就能把主要精力放在区分 “用户数据” 的变化和不变部分。要找到用户数据变化,那就需要进行对比。例如:覆盖升级前用户数据是 [1、2、3],覆盖升级后用户数据变为 [1、2、5、6],那么变化的用户数据就是 [5、6]。下面将要介绍三个测试维度对比。

2.2 三个测试维度

在上节思路指导下,我们采用了如下三个维度的对比用户数据。 我们还是以某 APP1.0 覆盖升级到 APP2.0 为例子。

用户数据 A/B/C 中都分别包含了:

那么通过对用户数据 A/B/C 进行不同的对比,可以得到不同的结论。从覆盖类型上看,我们可以分为 Struct、Data、Scale 三个维度类型。
####2.2.1 Struct 对比(校验升级代码)
Struct 对比数据 B(1.0 升级到 2.0 版本后 data 目录)和 C(全新安装 2.0 后 data 目录),来验证 “验证升级代码逻辑” 正确性。正常情况下,B 和 C 中所有 sqlite 数据表结构、配置 XML 文件结构、文本和二进制文件应该保持一致。如果不一致,就证明在 1.0 升级到 2.0 的升级代码中有 bug, 使得 1.0 升级到 2.0 后结构,无法和 2.0 全新安装保持一致。这种不一致可能存在三种情况:

例如:B 中的 switch 表

C 中的 switch 表

很明显是 1.0 升级到 2.0 的时候,对 switch 表升级代码漏掉了增加一列 phone 的操作。但是在 2.0 全新安装的时候, 在 switch 表确增加了 phone 字段。这就是我们要寻找的 Bug。关于这里的数据表中的值, 都是应用启动后默认的值。

例如:B 中的 switch 表数据类型

C 中的 switch 表数据类型

很明显是 1.0 升级到 2.0 的时候,对 switch 表升级代码漏掉了更改 name 字段类型的操作。但是在 2.0 全新安装的时候, 在 switch 表确 name 字段修改为了 Text 类型。这也是我们要寻找的 Bug。

例如:B 中的 switch 表

C 中的 switch 表

很明显是 1.0 升级到 2.0 的时候,对 switch 表升级代码漏掉了删除列 name 的操作。但是在 2.0 全新安装的时候, 在 switch 表确没有 name 字段。这种删除表的情况比较少,一般来说都是增加和修改。

####2.2.2 Data 类型(数据内容对比)
Data 数据对比 A(1.0 全新安装并且插入数据后 data 目录)和 B(1.0 全新安装并且插入数据后升级到 2.0 版本后 data 目录),来验证 “升级过程中数据变化”。这里的 “插入数据” 是指应用启动后插入样本数据。例如:浏览器的访问 Bookmark 表中制造一些样本数据,方便检验数据迁移的过程。

制造样本数据主要有两种方法:

通过手工操作应用,先制造样本数据。例如上例中,手动打开浏览器点击 “新浪网”。然后通过 sqlite 工具导出访问历史表中的数据保存。在下一次测试的时候, 在进行导入。

通过应用预留的 API 接口,可以直接进行数据插入。当然,这个和具体应用的可测性结构有关。

通过 GUI 自动化脚本,在应用界面模拟人工操作制造数据,也是一种不错的方法。

当数据 A 和 B 对比完全一致

我们基本可以认为数据迁移是正确的。为什么呢?因为如果 A 和 B 数据完全一致,那么在从 1.0 覆盖升级到 2.0 数据也应该是可用的。但是,如果出现 2.0 使用数据失败,那么这种问题在 2.0 版本的 “迭代” 测试中可以发现,而不属于 “覆盖安装” 的范畴。所以可以认为只要 A 和 B 数据完全一致,数据迁移就是正确的。

在数据 A 和 B 对比不一致

这种不一致并不能完全认为是错误的,这个需要测试人员同开发人员共同确认是否是 Bug。分为三种情况:

这是我们首先要搞清楚的问题,如何判定是数据修改,而不是数据删除和新增呢?例如:

A 中的 Bookmark 表

B 中的 Bookmark 表

从数据库数据分析角度,可以认为 id=1,id=2,id=3 的数据被删除,然后从新插入了 id=4,id=5,id=6 的数据。这种情况从业务上看,显然 url 字段保持不变,id 发生了变化,我们可以认为是修改。最后,我们采纳了这是修改的建议。因为,这样更符合业务情况,使测试人员对结果的判断上更加简单。

但是,修改的判断规则是如何定的呢?我们来看一下 Bookmark 表中的结构。

一般来说,Unique Constraint 约束的字段在表中都是联合主键。所以我们判断修改的算法是:

“主键” 或者 “联合主键” 其中二者满足其一,就认为是修改的数据。

有了判断数据修改的规则, 数据新增判断就很简单了。

有了判断数据修改的规则, 数据删除判断就很简单了。

2.2.3 Scale 类型(测试关注点对比)

Scale 类型对比 A(全新安装 1.0 版本 data 目录)和 C(全新安装 2.0 版本 data 目录),目的 “从数据层面观察两个版本差异, 给系统测试人员以指导”。例如:1.0 版本没有 bookmark 表,但是 2.0 版本中出现了 bookmark 表,就证明 2.0 新增了 bookmark 相关功能,需要提醒测试人员注意。

那么以上三个维度测试是如何实现的呢?请继续往下看。

2.3 自动化实现

体验地址: http://10.20.73.81:8080/OverrideTest/testAction! login

体验用户:ciro

体验密码:123

Note: 要创建测试任务,请注册自己的专用帐号。

步骤说明:

1.用户输入 APP 的 “最近 N 个历史版本 APK 包” 和 “最新版本 APK 包”。例如:N=2

历史包:1.0、2.0

最新包:3.0

循环 2 次:

第一次:1.0->3.0

第二次:2.0->3.0

2.系统将用户上传的 APK 包下发到测试手机。

3.虽然可以一次上传多个 “历史版本 APK 包”,但是系统中一个任务只包含:一个 “历史版本 APK 包” 和一个 “目标版本 APK 包”。很显然,N 个历史版本就会建立 N 个测试任务。在测试手机上 “全新安装” 一个任务的历史版本 APK 包。

4.启动 APP。

5.如果有样本数据的自动化脚本,这里将会进行样本数据插入。

6.拉取 APP 的 Data 目录下所有内容 A。

7.不卸载 “历史版本 APK”, 直接覆盖安装后的 “最新版本 APK”。

8.启动覆盖安装后的 APP。

9.APP 启动后,需要激活升级逻辑(参考:升级逻辑触发)。

10.拉取 APP 的 Data 目录下所有内容 B。

11.将用户上传的 APK 包下发到手机。

12.卸载已经安装的 APP,然后全新安装 “最新版本 APK”。

13.启动全新安装 “最新版本 APK”。

14.拉取 APP 的 Data 目录下所有内容 C。

15.将 Data 目录 A 和 B 输入文件对比模块进行对比(参考:Data 类型对比)。

16.将 Data 目录 C 和 B 输入文件对比模块进行对比(参考:Struct 类型对比)。

17.将 Data 目录 A 和 C 输入文件对比模块进行对比(参考:Scale 类型对比)。

18.文件对比模块,将输入的 sqlite 文件、xml 文件、文本文件和二进制文件进行对比。

19.保存对比的结果到 DB。

20.用户收到测试报告。

三、项目实战

3.1 经典实例

应用宝

历史版本:4.1、4.1.1、4.2、4.4、4.5、4.6、5.0、5.1

最新版本:5.2

测试类型:struct 对比(验证升级代码)

发现问题:

“全新安装 5.2 版本” 和 “任意 1 个历史版本升级到最新 5.2 版本” 对比,数据库新增了一张表 switch_phone_table。也就是说,升级逻辑代码漏掉了生成 switch_phone_table 表代码。

经过和测试人员沟通,发现这个表是应用宝 “换机助手” 的数据表。由于缺少了 switch_phone_table,“面对面换机” 在完成资料发送后,不会出现 “换机报告” 几个字,也无法点击。

最后测试人员确认是覆盖安装 Bug。这个 Bug 其实隐藏的很深,普通测试路径不容易覆盖到,但通过数据层来看,就很容发现。

腾讯地图

历史版本:3.1、4.0、4.1、4.7、4.8

最新版本:4.9

测试类型:struct 对比(验证升级代码)

发现问题:

腾讯地图 从 4.0 升级到 4.9 版本, 数据库中少生成一张 favorite.db/FavoriteStreetEntity 表。 这会导致 在 4.9 版本中收藏 “街景” 后, 数据无法写入数据库。如果重新启动腾讯地图, 刚才收藏的 “街景” 就会消失掉。

如果历史版本多,覆盖安装工作量大,人工测试就容易遗漏这样的测试路径。通过自动化观察数据层的迁移,就很容易发现问题,提高覆盖安装测试效率。

3.2 收益统计

本方案的主要收益,源于减少覆盖安装的测试关注点,缩短测试时间。通过在手机 QQ 浏览器项目实践,我们得到如下数据:

自动化建设时间:4 周=160 小时 * 人

样本数据采集时间:6(版本)x0.5(小时/版本)=3 小时\人

固定成本共计: 163 小时 * 人

由于自动化建设属于固定投入, 这部分收益通过长期多版本测试摊薄,可以忽略不计.样本数据采集时间是个主要耗时, 平均每个版本需要 0.5 小时 * 人. 一旦历史版本准备过一次样本数据,以后就不用再准备了,所以这部分耗时长期摊薄,也可以忽略。


自动化以后,平均每个版本覆盖安装测试关注点数量减少 50%。关注点的减少也直接导致测试时间的降低。

手机 QQ 浏览器项目组每次发布,关注最近 6 个版本的覆盖安装情况。从上图统计可以看出,通过自动化以后 “上线前覆盖安装测试时间” 缩短 60%,“集成覆盖安装测试时间” 缩短 60%。

其他腾讯产品试用后,得到以下数据:

通过数据表明经过本方案过滤后,覆盖安装测试验证点减少 50% 左右。

四、总结思考

4.1 样本数据插入

从项目结果中, 我们可以发现通过 Data 类型(数据内容对比),让我们更有可能发现问题。但是,这需要提前插入样本数据。有这样一些方法:

针对每个历史版本:测试人员通过手工操作构造用户数据。这个可以在迭代测试中就完成,不占用额外时间。

优点:操作简单;运行时间短。

缺点:手工操作耗时长;每个历史版本需要一份样本数据。

我们就采取的这种方案。

通过界面自动化,模拟用户操作创建用户数据。

优点:模拟用户操作,构造数据更准确。

缺点:界面自动化运行时间较长;每个版本需要维护一个自动化脚本(版本之间存在界面差别)。

这是一种 GUI 自动化的随机遍历操作。类似于 monkey 测试,但是点击是以界面控件为单位。参考:http://km.oa.com/group/18017/articles/show/150352?kmref=search

优点:不用写任何脚本和输入数据。

缺点:随机遍历创建用户数据可能存在不全面;界面控件随机操作运行时间较长。

### 4.2 升级逻辑激活
通过我们在多个项目实践,我们发现 APP 的升级逻辑触发时间点:

这种情况比较便于自动化处理,直接启动 APP 即可。

部分模块升级逻辑要推迟到模块启动才能触发,这就要求我们要有一套模块触发机制。这部分工作可以通过 UI 自动化工具完成,本项目中采用 QQDriver 自动化脚本完成。

4.3 与精准测试结合

理论上说,如果覆盖安装函数入口规范, 调用地点集中。例如:所有升级操作都在这样的函数中。

通过代码梳理,能够找到应用覆盖安装的函数入口。通过对比 “当前版本” 和 “历史版本” 覆盖安装函数代码差异,覆盖安装逻辑变化的功能模块,进行覆盖安装测试。从而缩短覆盖安装测试的时间。

但是经过手机 QQ 浏览器项目实际操作发现,覆盖安装代码都位置分散,而且函数写法不规范。跨大版本的 svn 代码对比,发现几乎所有功能模块的覆盖安装逻辑都有改动。这样就无法缩小测试范围,达到精准测试的目的。所以如果要实现精准化覆盖安装测试,覆盖安装函数入口函写法规范和调用地点统一是前提,这个可以给项目组提可测性需求实现。

本章完~~

本文连接:http://tmq.qq.com/2016/07/specialist-in-a-long-time-5-minutes-test-android-cover-installation/


TMQ(腾讯移动品质中心)是腾讯最早专注在移动 APP 测试的团队
我们专注于移动测试技术精华,饱含腾讯多款亿级 APP 的品质秘密,文章皆独家原创,我们不谈虚的,只谈干货!

扫码关注我们

扫一扫 关注 TMQ
精彩分享不断


↙↙↙阅读原文可查看相关链接,并与作者交流