专治时间长 —5分钟测试Android覆盖安装
tanlong4259
8年前
<h2>一、痛点</h2> <p><img alt="" src="https://simg.open-open.com/show/dc672412f59e3f916e13713da4106429.png"><br> 覆盖安装测试,作为一项基本的测试类型是不可或缺的。它存在的主要价值:验证老版本覆盖升级到新版本,用户和系统数据能够正确迁移,以及保障用户升级后的功能可用性。</p> <blockquote> <p>但是说他痛在什么地方呢?</p> <ul> <li> <p>需要测试的版本多</p> </li> <li> <p>每个版本需要覆盖的用例多</p> </li> </ul> </blockquote> <h2>二、解决方案</h2> <h3>2.1 思路</h3> <p>从哲学上说,任何事物都是发展变化的。我们需要在“变化”中找寻“不变”的本质和规律。在覆盖安装过程中,我们也要找到“不变”的部分,那就是我们能够“减少工作量”的地方。</p> <p>例如:某APP1.0版本覆盖升级到APP2.0版本。<br> <img alt="" src="https://simg.open-open.com/show/78eabde817889f9bc7bd8ecd1fc409c2.png"></p> <p>在这个过程中哪些是不变的部分呢?</p> <ul> <li>程序代码</li> </ul> <p>了解Android覆盖安装的同学都知道,覆盖安装后,APP1.0版本的程序代码,完全更新为APP2.0版本的程序代码。但是,这种变化会在“迭代”测试中完全保证。因为“迭代”测试中“全新安装”APP2.0程序代码和“覆盖安装APP2.0程序代码”是相同的。</p> <ul> <li>用户数据</li> </ul> <p>用户数据—用户使用APP过程中产生的数据。例如:用户使用“浏览器”打开了www.qq.com, 那么浏览器访问历史中的www.qq.com就是用户数据。很显然,用户数据在覆盖升级的过程中不应该被改变。不仅如此,升级后的用户数据必须能够正常访问使用。这样才能保证用户在APP覆盖升级后使用的连贯与一致性。当然,这是理想的情况,在覆盖升级过程中用户数据也有可能发生变化。<br> <img alt="" src="https://simg.open-open.com/show/141e054d157e0cf62af69333515cb961.png"><br> 很显然,(1)如果“用户数据(不变部分)”,能够保证在覆盖升级后正常访问使用,这部分测试工作量就能被释放。(2)针对“用户数据(变化部分)”,测试人员需要人工介入确认是否是问题。</p> <p>现在的主要问题就变成了:如何保证“用户数据(不变部分)”的功能正确性?</p> <p>【论据1】APP1.0覆盖升级为APP2.0后程序代码=全新安装APP2.0的程序代码。(成立)</p> <p>【论据2】APP2.0在全新安装状态下,“迭代测试”需要对主要功能进行“地毯式”的功能测试。只要使用“用户数据(不变部分)”作为测试数据,功能正确性就已经得到了保证。而在很多测试组,也确实就是这样做的。(成立)</p> <p>【结论】“用户数据(不变部分)”在覆盖升级后,不需要测试。(成立)</p> <p>有了这个结论,我们就能把主要精力放在区分“用户数据”的变化和不变部分。要找到用户数据变化,那就需要进行对比。例如:覆盖升级前用户数据是[1、2、3],覆盖升级后用户数据变为[1、2、5、6],那么变化的用户数据就是[5、6]。下面将要介绍三个测试维度对比。</p> <h3>2.2 三个测试维度</h3> <p>在上节思路指导下,我们采用了如下三个维度的对比用户数据。 我们还是以某APP1.0覆盖升级到APP2.0为例子。<br> <img alt="" src="https://simg.open-open.com/show/bf7bfb4cda9bbe5050eed1ff04c0586b.png"><br> 用户数据A/B/C中都分别包含了:</p> <ul> <li> <p>Sqlite数据库文件</p> </li> <li> <p>Shared preference配置XML文件</p> </li> <li> <p>文本和二进制文件</p> <p>那么通过对用户数据A/B/C进行不同的对比,可以得到不同的结论。从覆盖类型上看,我们可以分为Struct、Data、Scale三个维度类型。</p> </li> </ul> <p>2.2.1 Struct对比(校验升级代码)</p> <p>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全新安装保持一致。这种不一致可能存在三种情况:</p> <ul> <li>结构新增</li> </ul> <p>例如:B中的switch表<br> <img alt="" src="https://simg.open-open.com/show/2294a4b80e190f62d1ec57f7141624d6.png"></p> <p>C中的switch表<br> <img alt="" src="https://simg.open-open.com/show/e9683da1000d23dbb5880559f7707310.png"><br> 很明显是1.0升级到2.0的时候,对switch表升级代码漏掉了增加一列phone的操作。但是在2.0全新安装的时候, 在switch表确增加了phone字段。这就是我们要寻找的Bug。关于这里的数据表中的值, 都是应用启动后默认的值。</p> <ul> <li>结构修改</li> </ul> <p>例如:B中的switch表数据类型<br> <img alt="" src="https://simg.open-open.com/show/41109980879ce19b3335b7eda2e88ebd.png"></p> <p>C中的switch表数据类型<br> <img alt="" src="https://simg.open-open.com/show/6f191e16ead074ffef38d3e78d9b7cba.png"><br> 很明显是1.0升级到2.0的时候,对switch表升级代码漏掉了更改name字段类型的操作。但是在2.0全新安装的时候, 在switch表确name字段修改为了Text类型。这也是我们要寻找的Bug。</p> <ul> <li>结构删除</li> </ul> <p>例如:B中的switch表<br> <img alt="" src="https://simg.open-open.com/show/16ed427267ffca96af10440875ead211.png"></p> <p>C中的switch表</p> <p><img alt="" src="https://simg.open-open.com/show/2b4c37ed37e96168b0d5d1786f18494d.png"></p> <p>很明显是1.0升级到2.0的时候,对switch表升级代码漏掉了删除列name的操作。但是在2.0全新安装的时候, 在switch表确没有name字段。这种删除表的情况比较少,一般来说都是增加和修改。</p> <p>2.2.2 Data类型(数据内容对比)</p> <p>Data数据对比A(1.0全新安装并且插入数据后data目录)和B(1.0全新安装并且插入数据后升级到2.0版本后data目录),来验证“升级过程中数据变化”。这里的“插入数据”是指应用启动后插入样本数据。例如:浏览器的访问Bookmark表中制造一些样本数据,方便检验数据迁移的过程。<br> <img alt="" src="https://simg.open-open.com/show/591a7dcf3a709b67c4b156e5281a001d.png"><br> <strong>制造样本数据主要有两种方法:</strong></p> <ul> <li>数据导出法</li> </ul> <p>通过手工操作应用,先制造样本数据。例如上例中,手动打开浏览器点击“新浪网”。然后通过sqlite工具导出访问历史表中的数据保存。在下一次测试的时候, 在进行导入。</p> <ul> <li>API调用法</li> </ul> <p>通过应用预留的API接口,可以直接进行数据插入。当然,这个和具体应用的可测性结构有关。</p> <ul> <li>自动化脚本法</li> </ul> <p>通过GUI自动化脚本,在应用界面模拟人工操作制造数据,也是一种不错的方法。</p> <p><strong>当数据A和B对比完全一致</strong></p> <p>我们基本可以认为数据迁移是正确的。为什么呢?因为如果A和B数据完全一致,那么在从1.0覆盖升级到2.0数据也应该是可用的。但是,如果出现2.0使用数据失败,那么这种问题在2.0版本的“迭代”测试中可以发现,而不属于“覆盖安装”的范畴。所以可以认为只要A和B数据完全一致,数据迁移就是正确的。</p> <p><strong>在数据A和B对比不一致</strong></p> <p>这种不一致并不能完全认为是错误的,这个需要测试人员同开发人员共同确认是否是Bug。分为三种情况:</p> <ul> <li>数据修改</li> </ul> <p>这是我们首先要搞清楚的问题,如何判定是数据修改,而不是数据删除和新增呢?例如:</p> <p>A中的Bookmark表<br> <img alt="" src="https://simg.open-open.com/show/0a51a01c0bc3d69c3ff6bac2b9847674.png"></p> <p>B中的Bookmark表<br> <img alt="" src="https://simg.open-open.com/show/21e05a7ddbf8c1ac37c8838c8509a022.png"></p> <p>从数据库数据分析角度,可以认为id=1,id=2,id=3的数据被删除,然后从新插入了id=4,id=5,id=6的数据。这种情况从业务上看,显然url字段保持不变,id发生了变化,我们可以认为是修改。最后,我们采纳了这是修改的建议。因为,这样更符合业务情况,使测试人员对结果的判断上更加简单。</p> <p>但是,修改的判断规则是如何定的呢?我们来看一下Bookmark表中的结构。<br> <img alt="" src="https://simg.open-open.com/show/5b3abdc079edbd2bcfb6a4342f1822d8.png"><br> 一般来说,Unique Constraint约束的字段在表中都是联合主键。所以我们判断修改的算法是:</p> <p>“主键”或者“联合主键”其中二者满足其一,就认为是修改的数据。</p> <ul> <li>数据新增</li> </ul> <p>有了判断数据修改的规则, 数据新增判断就很简单了。</p> <ul> <li>数据删除</li> </ul> <p>有了判断数据修改的规则, 数据删除判断就很简单了。</p> <p>2.2.3 Scale类型(测试关注点对比)</p> <p>Scale类型对比A(全新安装1.0版本data目录)和C(全新安装2.0版本data目录),目的“从数据层面观察两个版本差异, 给系统测试人员以指导”。例如:1.0版本没有bookmark表,但是2.0版本中出现了bookmark表,就证明2.0新增了bookmark相关功能,需要提醒测试人员注意。</p> <p>那么以上三个维度测试是如何实现的呢?请继续往下看。</p> <h3>2.3 自动化实现</h3> <p>体验地址:<a href="/misc/goto?guid=4959676043410223619"> http://10.20.73.81:8080/OverrideTest/testAction!login</a></p> <p>体验用户:ciro</p> <p>体验密码:123</p> <p>Note: 要创建测试任务,请注册自己的专用帐号。<br> <img alt="" src="https://simg.open-open.com/show/254ddffd5494dd30e0cf3fff3db9917a.png"></p> <p><strong>步骤说明:</strong></p> <p>1.用户输入APP的“最近N个历史版本APK包”和“最新版本APK包”。例如:N=2</p> <p>历史包:1.0、2.0</p> <p>最新包:3.0</p> <p>循环2次:</p> <p>第一次:1.0->3.0</p> <p>第二次:2.0->3.0</p> <p>2.系统将用户上传的APK包下发到测试手机。</p> <p>3.虽然可以一次上传多个“历史版本APK包”,但是系统中一个任务只包含:一个“历史版本APK包”和一个“目标版本APK包”。很显然,N个历史版本就会建立N个测试任务。在测试手机上“全新安装”一个任务的历史版本APK包。</p> <p>4.启动APP。</p> <p>5.如果有样本数据的自动化脚本,这里将会进行样本数据插入。</p> <p>6.拉取APP的Data目录下所有内容A。</p> <p>7.不卸载“历史版本APK”, 直接覆盖安装后的“最新版本APK”。</p> <p>8.启动覆盖安装后的APP。</p> <p>9.APP启动后,需要激活升级逻辑(参考:升级逻辑触发)。</p> <p>10.拉取APP的Data目录下所有内容B。</p> <p>11.将用户上传的APK包下发到手机。</p> <p>12.卸载已经安装的APP,然后全新安装“最新版本APK”。</p> <p>13.启动全新安装“最新版本APK”。</p> <p>14.拉取APP的Data目录下所有内容C。</p> <p>15.将Data目录A和B输入文件对比模块进行对比(参考:Data类型对比)。</p> <p>16.将Data目录C和B输入文件对比模块进行对比(参考:Struct类型对比)。</p> <p>17.将Data目录A和C输入文件对比模块进行对比(参考:Scale类型对比)。</p> <p>18.文件对比模块,将输入的sqlite文件、xml文件、文本文件和二进制文件进行对比。</p> <p>19.保存对比的结果到DB。</p> <p>20.用户收到测试报告。</p> <h2>三、项目实战</h2> <h3>3.1 经典实例</h3> <p><strong>应用宝</strong></p> <p>历史版本:4.1、4.1.1、4.2、4.4、4.5、4.6、5.0、5.1</p> <p>最新版本:5.2</p> <p>测试类型:struct对比(验证升级代码)</p> <p>发现问题:</p> <p>“全新安装5.2版本”和“任意1个历史版本升级到最新5.2版本”对比,数据库新增了一张表switch_phone_table。也就是说,升级逻辑代码漏掉了生成switch_phone_table表代码。<br> <img alt="" src="https://simg.open-open.com/show/e83d2e6bd628cceb3b12c09995bc39b8.png"></p> <p>经过和测试人员沟通,发现这个表是应用宝“换机助手”的数据表。由于缺少了switch_phone_table,“面对面换机”在完成资料发送后,不会出现“换机报告”几个字,也无法点击。<br> <img alt="" src="https://simg.open-open.com/show/238fa26c9227764b7e3a1d0638c8a143.png"><br> 最后测试人员确认是覆盖安装Bug。这个Bug其实隐藏的很深,普通测试路径不容易覆盖到,但通过数据层来看,就很容发现。</p> <p><strong>腾讯地图</strong></p> <p>历史版本:3.1、4.0、4.1、4.7、4.8</p> <p>最新版本:4.9</p> <p>测试类型:struct对比(验证升级代码)</p> <p>发现问题:</p> <p>腾讯地图 从4.0 升级到 4.9版本, 数据库中少生成一张favorite.db/FavoriteStreetEntity表。 这会导致 在4.9版本中收藏“街景”后, 数据无法写入数据库。如果重新启动腾讯地图, 刚才收藏的“街景”就会消失掉。<br> <img alt="" src="https://simg.open-open.com/show/ed4ff5d35807c037f2a911da9c41b849.png"><br> 如果历史版本多,覆盖安装工作量大,人工测试就容易遗漏这样的测试路径。通过自动化观察数据层的迁移,就很容易发现问题,提高覆盖安装测试效率。</p> <h3>3.2 收益统计</h3> <p>本方案的主要收益,源于减少覆盖安装的测试关注点,缩短测试时间。通过在手机QQ浏览器项目实践,我们得到如下数据:</p> <ul> <li>成本</li> </ul> <p>自动化建设时间:4周=160小时*人</p> <p>样本数据采集时间:6(版本)x0.5(小时/版本)=3小时\人</p> <p>固定成本共计: 163小时*人</p> <p>由于自动化建设属于固定投入, 这部分收益通过长期多版本测试摊薄,可以忽略不计.样本数据采集时间是个主要耗时, 平均每个版本需要0.5小时*人. 一旦历史版本准备过一次样本数据,以后就不用再准备了,所以这部分耗时长期摊薄,也可以忽略。</p> <ul> <li>收益</li> </ul> <p><img alt="" src="https://simg.open-open.com/show/5bd80e626e0e74035336a2bb27bfc79e.png"><br> 自动化以后,平均每个版本覆盖安装测试关注点数量减少50%。关注点的减少也直接导致测试时间的降低。<br> <img alt="" src="https://simg.open-open.com/show/0afe4a82397ae96dfffdba1f264a6ebc.png"></p> <p><strong>手机QQ浏览器项目组</strong>每次发布,关注最近6个版本的覆盖安装情况。从上图统计可以看出,通过自动化以后“上线前覆盖安装测试时间”缩短60%,“集成覆盖安装测试时间”缩短60%。</p> <p>其他腾讯产品试用后,得到以下数据:<br> <img alt="" src="https://simg.open-open.com/show/a7b763df590cb844c67173b7851f2c05.png"></p> <p>通过数据表明经过本方案过滤后,覆盖安装测试验证点减少50%左右。</p> <h2>四、总结思考</h2> <h3>4.1 样本数据插入</h3> <p>从项目结果中, 我们可以发现通过Data类型(数据内容对比),让我们更有可能发现问题。但是,这需要提前插入样本数据。有这样一些方法:</p> <ul> <li>手工导出和自动化导入用户数据</li> </ul> <p>针对每个历史版本:测试人员通过手工操作构造用户数据。这个可以在迭代测试中就完成,不占用额外时间。<br> <img alt="" src="https://simg.open-open.com/show/769bbee1a31af50c23c4e553c6c155e4.png"></p> <p>优点:操作简单;运行时间短。</p> <p>缺点:手工操作耗时长;每个历史版本需要一份样本数据。</p> <p>我们就采取的这种方案。</p> <ul> <li>界面自动化脚本创建用户数据</li> </ul> <p>通过界面自动化,模拟用户操作创建用户数据。</p> <p>优点:模拟用户操作,构造数据更准确。</p> <p>缺点:界面自动化运行时间较长;每个版本需要维护一个自动化脚本(版本之间存在界面差别)。</p> <ul> <li>界面控件遍历操作创建用户数据</li> </ul> <p>这是一种GUI自动化的随机遍历操作。类似于monkey测试,但是点击是以界面控件为单位。参考:<a href="/misc/goto?guid=4959676043496724021">http://km.oa.com/group/18017/articles/show/150352?kmref=search</a></p> <p>优点:不用写任何脚本和输入数据。</p> <p>缺点:随机遍历创建用户数据可能存在不全面;界面控件随机操作运行时间较长。</p> <h3>4.2 升级逻辑激活</h3> <p>通过我们在多个项目实践,我们发现APP的升级逻辑触发时间点:</p> <ul> <li>APP启动时触发</li> </ul> <p>这种情况比较便于自动化处理,直接启动APP即可。</p> <ul> <li> APP启动后某功能激活时触发</li> </ul> <p>部分模块升级逻辑要推迟到模块启动才能触发,这就要求我们要有一套模块触发机制。这部分工作可以通过UI自动化工具完成,本项目中采用QQDriver自动化脚本完成。</p> <h3>4.3 与精准测试结合</h3> <p>理论上说,如果覆盖安装函数入口规范, 调用地点集中。例如:所有升级操作都在这样的函数中。</p> <p>通过代码梳理,能够找到应用覆盖安装的函数入口。通过对比“当前版本”和“历史版本”覆盖安装函数代码差异,覆盖安装逻辑变化的功能模块,进行覆盖安装测试。从而缩短覆盖安装测试的时间。</p> <p>但是经过手机QQ浏览器项目实际操作发现,覆盖安装代码都位置分散,而且函数写法不规范。跨大版本的svn代码对比,发现几乎所有功能模块的覆盖安装逻辑都有改动。这样就无法缩小测试范围,达到精准测试的目的。所以如果要实现精准化覆盖安装测试,覆盖安装函数入口函写法规范和调用地点统一是前提,这个可以给项目组提可测性需求实现。</p> <p>来自:http://tmq.qq.com/2016/07/specialist-in-a-long-time-5-minutes-test-android-cover-installation/?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io</p> <p> </p> <p>来自:http://blog.csdn.net/tmq1225/article/details/52126314</p> <p> </p>