Android内存泄露测试不再蓝瘦,香菇

 

        在进行Android内存泄露分析时,面对成千上万个对象,你是否蓝瘦,香菇?作为测试人员你在进行内存泄露测试之后,是否有勇气告诉开发同事程序已经没有内存泄露,可以放心发布了?

       众所周知,内存泄露测试难点在于准确的定位出泄露的对象。现在小哥有种方法通过一条命令就高效全面的得到Android程序内存泄露对象,让你不再蓝瘦,香菇!

1.Android内存泄露自动化分析方法

      目前我知道的几种常用的Android内存泄漏方案主要有MAT、腾讯内部开发的FinderLeakCanary以及浏览器目前使用的方法。

几种方法,我们通过以下的几个纬度进行对比。

MAT Finder LeakCanary QB方案
手动/自动 手动 手动 自动 自动
分析准确度
分析难度
分析效率
是否修改代码
应用场景 所有 所有 部分 所有

最原始的Java内存泄露分析方式,是通过MAT将测试操作前后的Hprof文件进行对比,然后根据对比结果来尝试识别出泄露对象,这种方法效率比较低。

如果使用腾讯的Finder工具来进行泄露分析,效率将会提高很多,但还是手动执行,也存在时间浪费的问题。

也可以使用LeakCanary或者腾讯自研的LeakInspector来测试,由于这两个工具是自动分析,效率会更加高效。但需要修改代码,把工具的SDK引入到工程中。此外针对不退出Activity的测试场景,不能很好的处理。

而我们的分析方法,一条命令就可以完成分析,并输出详细的泄露对象,以及调用关系。

      从前面的表中可以看LeakCanary各方面都挺优秀,但是我们为什么没有使用它呢?这是因为QQ浏览器很多场景都是在MainActivity中进行的,比如打开网页,此时MainActivity并不会Destroy,直接使用LeakCanary无法进行泄漏分析,因此我们才考虑自己实现一个分析工具。

QQ浏览器项目中,使用的分析工具叫做HprofComparator,这是我们自己开发的一个Eclipse Application,其原理与Finder的对比原理一致,但是加入了泄露分析的策略,可以通过命令行直接运行,更加的高效。

 

2.浏览器内存泄漏测试方案实施

1) 测试场景选择

做内存泄漏测试一定要全面的测试才敢通知项目组放心发布,目前QQ浏览器选择对所有的画面进行泄漏排查。

内存出现泄漏的前提条件一定是有新的内存分配,所以测试场景会选择有新对象创建的场景,并结合用户的使用场景和频率来确定优先级。测试场景主要有以下三种情况:

      Ø  新画面打开

由于新的画面打开,就会创建新的Activity,并有许多其他对象被创建。

      Ø  画面旋转

当屏幕旋转时,Orientation设置发生了改变,当前显示的Activity会被重新创建。

      Ø  滑动屏幕

滑动屏幕会使屏幕中显示的对象(比如浏览器小说阅读内容)创建。

2)内存泄漏分析

      测试方法就是重复运行以上选择的场景,将整个测试过程分几个阶段获取到Hprof文件并保存。这个过程不详细阐述,下一部分会阐述我们的自动化方案。我们先看下拿到Hprof文件后人工分析的过程。

浏览器的内存分析工具运行的方法如下图所示。


      运行完毕后将得到如下的分析结果文件。

需要重点查看的文件是suspicion文件,其内容如下图所示。

首先从图中可以看出 NewActivity 的对象泄漏了,该对象在操作过程中新创建出5个对象,内存增长了93696字节,内存中该对象的总数量为13个。

接着从图中的调用关系可以分析出,TextManager有一个listeners的数组持有了 NewActivity 的对象。

最后对比源代码查看输出结果可以一目了然的看出TextManager是一个单例的对象,而泄露对象应该是注册了TextManager 的 ITextChangeListener,没有取消注册引起的泄漏。

我相信当测试人员把泄漏对象的根因连同Bug一起提交给开发时,开发同事们一定会觉得你很牛X

      此外泄露分析过程中还有一种常见情况,就是很多对象泄露是因为同一个原因,如下图是通过Finder对比得到的结果。


从这个图中可以看出泄漏对象非常多,如果我们逐个对对象进行原因分析的话,将浪费大量的时间,但是实际上这些对象的泄漏都是因为 NewActivity 的泄漏造成的。为了提高我们的分析效率,HprofComparator对泄漏对象进行了去重处理。

如上图所示,BC都为泄露嫌疑,从BCCallstack可以看出BC的父对象(B引用C),因此只要B释放了,C也会释放。这种情况时我们就会将C 合并到B,最终结果输出B。如前面的 suspicion 文件内容中显示,有92个对象被duplicate到了 NewActivity 上。这样做之后输出结果会被大量的精简,需要分析原因的对象数量将会大大减少,节省了许多的时间。

3)关键字驱动的自动化方案

QQ浏览器项目中一开始还是人工获取Hprof文件,这样做的测试效率比较低。为了提高测试效率我们也引入了自动化测试,但如何才能让自动化测试投入产出比比较高呢?

在分析了我们的测试场景和测试执行过程后,我发现内存泄露测试基本上可以分为做操作和获取Hprof文件,而操作又分为点击、滑动、旋转屏幕、等待和输入文字等。整个测试过程中除了需要确保操作是正确的外,并不需要功能的验证。

基于这些特点,我选择关键字驱动的自动化方案,就是为了以简便的方式来实现自动化,减少开发和维护成本。

如下图所示,在测试打开小说书城的场景,需要启动程序,然后点击小说入口,然后返回,需要重复打开小说的过程。在脚本中直接省略了打开应用程序的操作,repeat关键字说明后续的步骤是需要重复操作的,而点击小说入口则仅以“小说”替代。这样就使测试脚本足够简单,任何刚入门的测试人员都可以完成。


在脚本要进行的操作都以关键字描述,测试时这些关键字都将转换成控件进行控件查找,或者转换成坐标直接点击。



以上的脚本还只是测试数据,我们需要一个测试驱动程序来分析测试脚本,以及执行对应的操作。在QQ浏览器项目中采用Python在实现驱动程序,并结合Appium实现自动化测试。驱动程序的执行流程非常简单,它就负责解析数据文件,然后执行关键字对应的操作。脚本的解析如下图的代码所示,每一个关键字会被处理成对应的命令,并存放到列表里。


以上测试运行过程中还会伴随着截图,用于后期分析时确保测试是正确执行的。当测试运行完毕后,hprof文件将被Pull到电脑上,并使用自动分析工具进行泄漏分析。

4)测试运行情况

目前内存泄露测试已经加入到每个版本的常规测试中,每个版本平均能扫描出10+内存泄漏的问题。

手动测试和自动化测试对比情况如下图所示,内存泄露自动化测试的效率提升主要体现两个方面:

      Ø  测试效率提升。人工测试150+用例大概需要5人日,而现在可以一晚上运行完毕。

      Ø  分析效率提升。人工通过Finder进行分析,需要近5个人日,而现在仅需要1天就可以完成。

      通过这样的方法不仅保证了测试的准确性,也保证了测试的全面性,整体测试效率提升85%

 

3.后续思考

      由于浏览器的内存泄漏分析方法与被测试的应用无关,后续将考虑实现泄漏分析平台化,这样可以让更多的项目快速的应用起来.

目前在浏览器项目使用了一种的基于模型的用例生成方法,但模型需要人工创建,以后可以尝试对任意的应用程序自动生成模型并自动创建用例.

 

 

版权所属,禁止转载

11,921 0 117

发表评论