移动端的测试中,因为回归一些逻辑分支比较多的功能时工作量比较大,且不太适合用UI完成,尝试通过单元测试来完成。几经波折终于完成了一个功能的UT用例并在CI上部署运行,现总结如下:
一、Robolectric简介
Robolectric是一款运行在JVM之上的Android单元测试框架。传统的Android Instrumentation单元测试框架必须运行在虚拟机上,测试速度较慢,效率低。而Robolectric模拟了Android sdk的jar包,其会在JVM加载Android.jar包的时候,重写其中类的方法,让这些方法有返回值,不会抛出stub异常 ,或者利用Shadow Objects来模拟方法的实现。因此,Robolectric完全脱离了Android模拟器,用例的运行速度大幅提高。
二、本地环境搭建
在eclipse中导入或者新建被测android工程
在android工程的根目录下新建一个test文件夹,在test文件夹中新建src文件夹,用于存放测试代码
创建一个新的java工程
把java工程下默认的src移除bulid path(点击鼠标右键可见),把src删除
把android工程下的test/src文件夹,加到java工程来(点击鼠标右键,选择build path、link souce),就可以在java工程中看到测试代码了,但实质上代码是放在android工程的目录下的
Java工程,右键build path 、configure build path中,Projects里把android工程加进来,注意调整顺序使blog_android位于robolectric的下面
configure build path中,Add Library,把juint4加进来
java工程,把下面依赖的android包和robolectric包导入,可把依赖包存放在android工程的test/libs下。必须的包:android.jar、maps.jar、robolectric-2.4-jar-with-dependencies.jar
三、编写并运行用例
Robolectric是基于juint4的,所以样式类似于普通juint的单元测试,以下是一个简单的例子
@RunWith(RobolectricTestRunner.class)
@Config(emulateSdk=18)
public class ButtonTest {
ButtonActivity buttonActivity;
Button button1;
TextView textview;
@Before
public void setUp() throws Exception {
buttonActivity = Robolectric.buildActivity(ButtonActivity.class).create().get();
textview = (TextView) buttonActivity.findViewById(R.id.TextView1);
button1 = (Button) buttonActivity.findViewById(R.id.Button1);
}
@Test
public void buttontest() throws Exception {
button1.performClick();
assertEquals("你点击了开始按钮!", textview.getText().toString());
}
}
运行用例,run configuration设置,test下最下方Select选择Eclipse JUnit Launcher;Arguments里Working directory选择android工程。
当用于项目的时候还有一些需要注意的地方:
网上有的例子启动activity,使用buttonActivity = new ButtonActivity(),我试了下在robolectric-2.4-jar-with-dependencies包下是不行的;
如果配置的android sdk版本比较高,比如@Config(emulateSdk=21),运行用例会提示Robolectric还不支持;
Robolectric默认采用项目根目录下的AndroidManifest.xml和res资源文件,当采用上述方法运行用例时,则会采用android工程下的AndroidManifest.xml和res。如果不想用默认的,也可以指定文件:@Config(manifest = "",resourcesDir="")
运行用例的时候,Roblectric会先去创建Android工程的Application的实例。在实际的项目中,发现有一些清理的方法和xml的写法robolectric不识别,一种做法是在BeforeClass中把Application的class文件和需要修改的xml文件替换掉,在AfterClass中换回来。Robolectric也提供一种替换方式:@Config(application = CustomApplication.class)
四、CI部署与持续集成
采用ant编译运行测试代码,编写build构建文件。需要先编译开发代码,再编译测试代码,才能运行用例,target可以按照如下形式组织:
有几点需要注意的地方:
如果build文件没有放到android工程的根目录下且代码中没有指定res和AndroidManifest.xml,在运行测试用例前需要把android工程的res和AndroidManifest.xml拷贝到build文件的同级目录下;
classpath中junit.jar要位于android.jar之前;
编译和运行测试用例的classpath中需要包含编译开发代码的目标路径和开发代码的所有依赖jar包。
Jenkins上部署运行:虽然在本地创建了一个java工程,但其实代码源码是存放在android工程中的,因此只需要从git上更新android工程,然后ant运行build构建文件,最后再配置发送邮件。注意:生成R文件,如果运行用例的服务器是linux的,需要在工程根目录下手动创建gen文件,而windows下会自动创建。
本文来自网易实践者社区,经作者陈天昊授权发布。