单元测试TestCase
Android的sdk提供了对项目进行单元测试的功能,开发包的android.test下面便是专门用来单元测试的类。单元测试的作用是通过模拟文本输入和手势输入(如点击操作),从而让app自动执行一系列的操作,这样就能够检查程序是否运行正常。
下面是搭建测试工程的具体步骤:
1、首先当然你得有一个待测试的app工程,最简单的如带有一个编辑框的Hello World工程;
2、其次在ADT中创建测试工程,操作步骤为依次选择菜单“File”——“New”——“Other...”——“Android Test Project”,然后在弹窗中选择待测试的工程,点击Finish按钮完成创建。
打开测试工程的AndroidManifest.xml,会看到里面多了两处配置,截图如下:
第一处配置是instrumentation节点,表示要对哪个工程进行测试,其中android:name属性固定填“android.test.InstrumentationTestRunner”,android:targetPackage属性填待测试的工程包名。
另一处配置是uses-library节点,android:name属性值固定填“android.test.runner”。
3、在测试工程中创建一个TestCase的派生类,该派生类可从ActivityTestCase可继承自ActivityTestCase,也可继承自InstrumentationTestCase。
4、右击测试工程,在右键菜单中依次选择“Run As”——“Android JUint Test”,即可在测试设备上看到单元测试的运行页面。
下面是一个TestCase派生类的代码例子:
import android.os.SystemClock; import android.test.InstrumentationTestCase; import android.util.Log; public class Sampletest extends InstrumentationTestCase { private final static String TAG = "Sampletest"; private MainActivity activity = null; private Button btn = null; private TextView tv = null; //初始化设置,初始化页面对象与控件对象 @Override protected void setUp() { try { super.setUp(); } catch (Exception e) { e.printStackTrace(); } Intent intent = new Intent(); intent.setClassName("com.example.test", MainActivity.class.getName()); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); activity = (MainActivity) getInstrumentation().startActivitySync(intent); tv = (TextView) activity.findViewById(R.id.tv); btn = (Button) activity.findViewById(R.id.btn); } //垃圾清理与资源回收,测试完毕退出页面 @Override protected void tearDown() { activity.finish(); try { super.tearDown(); } catch (Exception e) { e.printStackTrace(); } } //活动功能测试,凡是public且以test打头的函数,均会被JUnit测试到 public void testActivity() throws Exception { Log.d(TAG, "test the Activity"); SystemClock.sleep(1000);//先sleep一会,这时的文字是hello for(int i=0; i<1000; i++) { //点击1000次 getInstrumentation().runOnMainSync(new PerformClick(btn)); } SystemClock.sleep(2000);//再sleep一会,这时看到的文字是Hello Android Log.d(TAG, tv.getText().toString()); assertEquals("Hello World", tv.getText().toString()); //注意,这里做了一个判断,判断当前tv标签控件的文字是不是Hello World,当然不是,所以这句判断是错的!!!! } private class PerformClick implements Runnable { Button btn; public PerformClick(Button button) { btn = button; } public void run() { btn.performClick(); } } }
如果你是在Android Studio上开发,那在创建Android工程时便已生成测试类,默认名称是ApplicationTest.java,测试代码的编写规则同Eclipse,这里就不再赘述。
自动化测试框架Robotium
上面提到的测试代码编写,其实比较繁琐,一般只用于单个页面的测试,所以简单带过不作详述。实际工作中常用的是Robotium这个工具,它是Android官方提供的测试框架,不但方便开发者编写测试代码进行调试,而且也支持在多个页面中跳转测试。
使用Robotium仍然是要一步一步创建测试工程,只不过在测试工程中导入Robotium的jar包,并在TestCase中使用Solo类编写测试代码。Robotium的最新jar包是robotium-solo-5.3.1.jar,下载地址是 http://pan.baidu.com/s/1qXHT9OK
Robotium的代码编写不难,我就直接上官方的demo代码,补充中文注释便一目了然了,代码如下:
import com.robotium.solo.Solo; import com.example.android.notepad.NotesList; import android.test.ActivityInstrumentationTestCase2; public class NotePadTest extends ActivityInstrumentationTestCase2<NotesList>{ private Solo solo; public NotePadTest() { super(NotesList.class); } @Override public void setUp() throws Exception { //初始化一个Solo对象 solo = new Solo(getInstrumentation(), getActivity()); } @Override public void tearDown() throws Exception { //测试结束要关闭所有打开的页面 solo.finishOpenedActivities(); } //测试添加记录 public void testAddNote() throws Exception { //解锁屏幕 solo.unlockScreen(); //点击菜单项“Add note” solo.clickOnMenuItem("Add note"); //声明NoteEditor这个页面已经打开 solo.assertCurrentActivity("Expected NoteEditor activity", "NoteEditor"); //往序号为0的编辑框输入“Note 1” solo.enterText(0, "Note 1"); //回到上一页 solo.goBack(); //点击菜单项“Add note” solo.clickOnMenuItem("Add note"); //往序号为0的编辑框输入“Note 2” //注意enterText和typeText的区别在于:typeText是模拟键盘输入, //所以typeText的字符串中如果包含“\n”会转为换行符,而enterText只会原样显示字符串“\n” solo.typeText(0, "Note 2"); //回到上一页 solo.goBack(); //捕捉屏幕截图并保存到默认路径:Environment.getExternalStorageDirectory()+"Robotium-Screenshots/". solo.takeScreenshot(); //检查是否找到“Note 1”和“Note 2” boolean notesFound = solo.searchText("Note 1") && solo.searchText("Note 2"); //如果找到则通过测试 assertTrue("Note 1 and/or Note 2 are not found", notesFound); } public void testEditNote() throws Exception { //点击列表视图的第二项,即进入到该记录的编辑页面 solo.clickInList(2); //隐藏软键盘 solo.hideSoftKeyboard(); //变更屏幕方向为水平方向 solo.setActivityOrientation(Solo.LANDSCAPE); //点击菜单项“Edit title” solo.clickOnMenuItem("Edit title"); //往序号为0的编辑框追加输入“ test” solo.enterText(0, " test"); //回到上一页 solo.goBack(); //设置屏幕方向为垂直方向 solo.setActivityOrientation(Solo.PORTRAIT); //使用通配符查找是否存在指定文本 boolean noteFound = solo.waitForText("(?i).*?note 1 test"); //如果找到则通过测试 assertTrue("Note 1 test is not found", noteFound); } public void testRemoveNote() throws Exception { //使用通配符查找是否存在包含test的文本 solo.clickOnText("(?i).*?test.*"); //点击菜单项“Delete” solo.clickOnMenuItem("Delete"); //查找是否存在文本“Note 1 test” boolean noteFound = solo.searchText("Note 1 test"); //如果没找到则通过测试 assertFalse("Note 1 Test is found", noteFound); //长按文本“Note 2” solo.clickLongOnText("Note 2"); //在弹出的上下文菜单中点击文本“Delete” solo.clickOnText("Delete"); //等待100毫秒后查找是否存在文本“Note 2” noteFound = solo.waitForText("Note 2", 1, 100); //如果没找到则通过测试 assertFalse("Note 2 is found", noteFound); } }
功能测试/常用模拟器
ADT和Adnroid Studio都提供了自带的模拟器,用于开发者测试app的页面功能,可是众所周知,自带的模拟器又耗资源、运行又慢,所以实际开发中基本不用自带模拟器。那么调试app的设备主要有下面几种:
1、下载并安装国外模拟器Genymobile,还要在Eclipse中安装Genymobile插件,这样便能在Eclipse中使用Genymobile。但该模拟器搭建环境很繁琐,首先下载前要在它的官网注册,安装时又要指定虚拟机,不够傻瓜。
2、安装国内的模拟器,比如博主一开始用的是夜神模拟器,后来又改用逍遥安卓模拟器。总的来说,国产模拟器不但操作方便,而且比国外模拟器更贴近国人的使用习惯。
3、把真机用数据线插到电脑的usb口,直接使用真机测试app。但这对真机的要求比较高,如果真机的系统版本比较老,那就无法测试高版本上的新特性。
性能测试工具
DDMS
DDMS是ADT自带的测试监控服务,实际开发中一般主要用到它的三个功能:
1、首先当然是LogCat服务,开发者都在该日志窗口查看app运行日志;
2、其次是File Explorer窗口,通过该窗口我们可以往测试设备上传文件,或者下载文件;
3、再次就是检查内存泄漏时用到的Heap窗口,有关内存泄漏的介绍参见《Android开发笔记(七十五)内存泄漏的处理》,下面是Heap窗口的内存数据截图:
APT
APT是一个用于app性能测试的Eclipse插件,源码主页在https://code.csdn.net/Tencent/apt/tree/master。
使用的时候,只需把最新的jar包如APT_Eclipse_Plugin_1.1.8.jar复制到Eclipse的plugins目录,然后重启Eclipse即可。在ADT上依次选择菜单“Window”——“Open Perspective”——“Other”——“APT”即可打开APT透视图,即可在该页面查看手机上各进程的cpu和内存使用情况。
不过我这边打开APT后并未看到详细的运行情况,不知咋回事,查看APT的项目主页,发现它最后一次更新时间是2014年12月份,其开发团队后面转去另一个性能测试项目GT了,所以想想还是不必深究APT了。
GT
GT的官网是http://gt.qq.com/。下面是官网对它的介绍:GT(随身调)是APP的随身调测平台,它是直接运行在手机上的“集成调测环境”(IDTE, Integrated Debug Environment)。利用GT,仅凭一部手机,无需连接电脑,您即可对APP进行快速的性能测试(CPU、内存、流量、电量、帧率/流畅度等等)、开发日志的查看、Crash日志查看、网络数据包的抓取、APP内部参数的调试、真机代码耗时统计等。
使用GT要在官网下载GT安装包,如最新版本是GT_2.2.6.4.apk,把该apk包安装到手机上,启动GT后就能对指定app进行性能监控。下面是GT的首页截图:
机型测试网站
app在真机和模拟器上测试通过了,这并不意味着万事大吉,因为Android是个开源的系统,各厂家都可以进行定制修改,所以在A品牌手机上运行正常的app,也许在B品牌手机上就会发生崩溃。可是Android的手机厂家不像ios只有苹果一家,而是百花齐放、千军万马,国内厂家就有华为(mate、荣耀)、小米(小米、红米)、步步高(vivi、oppo)、联想、中兴、酷派、魅族、TCL、HTC等等,国外厂家则有三星、LG、索爱等等,要想在这么多品牌手机上都测试一遍,测试人员都要累趴了。
基于此,现在有多个专业的云测试网站,它们提供了少则一百、多则上万机型的兼容测试服务,开发者只需注册并上传app安装包,即可在一天之内收到多种机型的测试报告,极大方便了我们的测试工作。下面是几个比较大的云测试网站:
TestIn : http://testin.cn/
易测云 : http://www.yiceyun.com/
智测云 : http://www.smarterapps.cn/
百度MTC : http://mtc.baidu.com/
腾讯优测 : http://utest.qq.com/