Android系统自动化测试简述

发表于:2011-06-24来源:未知作者:admin点击数: 标签:
研究Android源码发现框架层中有很多对测试有帮助的类、方法都被加上了@hide注解或是声明为private的,无法从app层访问。自然而然我们想到了java的反射机制, java反射允许我们访问这样的类和方法。 在上面的基础上,国外有人开发出了Robotium工具,可

  入职两月有余,从之前的android app开发到现在的测试框架开发,工作中遇到很多问题,趁这次机会分享一下。

  Android自动化测试目前可借鉴的经验不多,现在采取的方式就是通过java代码对Activity和View进行操作,目前已知的入口是Instrumentation类。

  Instrumentation与Activity均位于android.app包下,这个包内还有诸如ActivityManagerNative这种不对App层开放的类,通过查看Android源码发现Activity类中诸如startActivity(Intent intent)这样重要的方法都是通过Instrumentation实现,Instrumentation中也提供了一系列对Activity生命周期控制的方法。以Instrumentation为基础,Android SDK在Junit基础上进行了扩展,提供了AndroidTestCase类及系列子类,其中最重要的一个类是ActivityInstrumentationTestCase2。

  基于Instrumentation的测试框架的工作原理SDK中的这张图说明的很清楚了:

  研究Android源码发现框架层中有很多对测试有帮助的类、方法都被加上了@hide注解或是声明为private的,无法从app层访问。自然而然我们想到了java的反射机制, java反射允许我们访问这样的类和方法。

  在上面的基础上,国外有人开发出了robot/" target="_blank" >Robotium工具,可以在有app源码或apk的情况下进行自动化黑盒测试

  但是Robotium目前的缺点也很明显,无法对WebView进行操作,这对大量使用WebView的淘宝Android客户端来说无疑是很大的限制。

  而且Robotium提供的API是面向过程的,测试代码的可扩展性差。

  我们需要一个面向对象的,可对WebView进行操作的自动化测试框架,这就催生了TMTS(Taobao Mobile Test Studio)框架。

  TMTS立项时还试图着重解决另一个问题,就是Instrumentation框架下testapp和app运行在一个进程中 ,app crash会导致testapp一并crash。当时和士敦一起研究了Instrumentation、Activity的启动流程,甚至想去研究一下dalvik是如何解析Manifest文件的,最后也没有想到好的方法,收获就是了解了android更底层一些的细节,这个问题现在先搁置了起来。

  从测试代码方面来看, Robotium中采用的是actionMethod(View, arg)的方式,TMTS中采用getView(id).actionMethod(arg)的方式,更加符合java的编程习惯。TMTS测试代码的编写也就是分三步,找到View,调用View的相应的action方法,断言。

  TMTS框架主要思想就是通过反射机制调用Android框架层API拿到当前Activity的所有View,在此基础上返回需要获得的View对象,对获得的View通过Instrumentation封装一些此View常用的操作,最后返回,这就是TmtsView及其子类。

  这种方式缺点也很明显,对每个从android.View继承来的子类,如果其中有特殊的操作,就需要封装出一个对应的TmtsView子类。

  还有一个缺点就是目前是通过View在布局文件中声明的id去寻找,这样测试人员在编写代码时需要对app的源码非常熟悉,了解当前操作的view的id是多少,在传递id参数时还有可能写错。之后我们对这个方式进行了一些改进,使用SDK自带的hierarchyviewer工具获得view的id;对每个布局文件进行解析生成java类,这个类中会提供方法返回布局文件中的所有带id的view,经过讨论,最后按view子类型来对一个布局中的view进行归类。

  现在测试代码从getView(id).actionMethod(arg)演变成了Layout(layout.class).ViewType().view().actionMethod(arg)的方式,代码虽然变长了,但是出错的可能性大大降低了。

  Bug的定位离不开日志,因而日志系统也是一个测试框架重要的组成部分,Android的Log类中提供了一系列的静态方法可以在IDE中打印日志。在TMTS中,提供TmtsLog类,除日志打印外可将日志内容实时保存至SD卡指定目录,在框架代码中的关键部位都加上了这样的日志用来保存异常时的调用栈信息,用户的测试代码中也可以加上对TmtsLog的调用跟踪测试代码执行进度,TmtsLog将为每个测试类保存一份这样的日志文件,同时包含用户的过程日志和框架异常日志,文件名以精确到毫秒的日期加以区分。

  项目做到这里远远没有结束,套用屈原的一句话就是路漫漫其修远兮。

  后面计划解决的问题有:

  1.跨进程测试,让testapp和app运行在两个不同的进程中,这是一个大坑。

  2.稳定性问题,目前框架中有很多地方硬编码Thread.sleep()去等待一个View加载完成,避免对空的View进行操作,或者是对一个view进行set操作后,也需要等待一段时间让操作生效。希望能找到一种回调机制优雅的解决。

  而且Robotium提供的API是面向过程的,测试代码的可扩展性差。

  我们需要一个面向对象的,可对WebView进行操作的自动化测试框架,这就催生了TMTS(Taobao Mobile Test Studio)框架。

  TMTS立项时还试图着重解决另一个问题,就是Instrumentation框架下testapp和app运行在一个进程中 ,app crash会导致testapp一并crash。当时和士敦一起研究了Instrumentation、Activity的启动流程,甚至想去研究一下dalvik是如何解析Manifest文件的,最后也没有想到好的方法,收获就是了解了android更底层一些的细节,这个问题现在先搁置了起来。

  从测试代码方面来看, Robotium中采用的是actionMethod(View, arg)的方式,TMTS中采用getView(id).actionMethod(arg)的方式,更加符合java的编程习惯。TMTS测试代码的编写也就是分三步,找到View,调用View的相应的action方法,断言。

  TMTS框架主要思想就是通过反射机制调用Android框架层API拿到当前Activity的所有View,在此基础上返回需要获得的View对象,对获得的View通过Instrumentation封装一些此View常用的操作,最后返回,这就是TmtsView及其子类。

  这种方式缺点也很明显,对每个从android.View继承来的子类,如果其中有特殊的操作,就需要封装出一个对应的TmtsView子类。

  还有一个缺点就是目前是通过View在布局文件中声明的id去寻找,这样测试人员在编写代码时需要对app的源码非常熟悉,了解当前操作的view的id是多少,在传递id参数时还有可能写错。之后我们对这个方式进行了一些改进,使用SDK自带的hierarchyviewer工具获得view的id;对每个布局文件进行解析生成java类,这个类中会提供方法返回布局文件中的所有带id的view,经过讨论,最后按view子类型来对一个布局中的view进行归类。

原文转自:http://www.ltesting.net