安卓应用单元测试技术分享

使用ThreadingTest进行安卓应用单元测试

1、Android单元测试的编写

Android单元测试有两种方法,首先作为java程序,可以试用JUnit Test进行测试,另外也可使用Android JUnit Test进行单元测试。

1)、JUnit Test进行单元测试

JUnit对Android应用程序进行单元测试需要使用Java命令来启动或者在eclipse里面将启动的Bootstrap Entries改为JRE,但是这种只能测试逻辑代码,因为是是运行在JVM上,而不是Android系统中,所以不能测试Android有关的代码。

使用JUnit测试的代码,需要在函数的之前加@Test,函数必须为public类型,在eclipse中,在类上右击,选择JUnit Test即可进行测试。

2Android
JUnit Test
进行单元测试

Android JUnit Test单元测试是一组直接或间接继承自junit.framework.Testcase的类集合,入口是InstrumentationTestRunner。

使用Android JUnit Test测试,也存在两种测试方法,测试驱动与测试代码在同一工程下和测试驱动和测试代码位于不同工程,两者之间并无巨大差异,只是在测试时,前者只安装一个App,后者安装两个App。

如下为一个单元测试的实例:

步骤 1:准备好需要测试的源代码


package com.zeroone.unittest;

import android.os.Bundle;

import android.app.Activity;

import android.view.Menu;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.TextView;

public class Sample extends Activity {

private TextView myText = null;

private Button button = null;

@Override

protected void onCreate(Bundle
savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

myText = (TextView) findViewById(R.id.text1);

button = (Button) findViewById(R.id.button1);

button.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View arg0) {

myText.setText("Hello Android");

}

});

}

public int add(int i, int j) {

try {

Thread.sleep(1500);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return (i + j);

}

}

步骤2:添加测试类,编写测试代码,测试onClick和add函数


package com.zeroone.unittest.test;

import com.zeroone.unittest.R;

import com.zeroone.unittest.Sample;

import android.content.Intent;

import android.os.SystemClock;

import android.test.InstrumentationTestCase;

import android.util.Log;

import android.widget.Button;

import android.widget.TextView;

public class SampleTest extends InstrumentationTestCase {

private Sample sample = null;

private Button button = null;

private TextView text = null;

// 初始设置

@Override

protected void setUp()  {

try {

super.setUp();

} catch (Exception e) {

e.printStackTrace();

}

Intent intent = new Intent();

intent.setClassName("com.zeroone.unittest", Sample.class.getName());

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

sample = (Sample)
getInstrumentation().startActivitySync(intent);

text = (TextView) sample.findViewById(R.id.text1);

button = (Button) sample.findViewById(R.id.button1);

}

// 垃圾清理与资源回收

@Override

protected void tearDown()  {

sample.finish();

try {

super.tearDown();

} catch (Exception e) {

e.printStackTrace();

}

}

// 活动功能测试

public void testActivity() throws Exception {

Log.v("testActivity", "test the Activity");

SystemClock.sleep(1000);

getInstrumentation().runOnMainSync(new PerformClick(button));

SystemClock.sleep(1000);

assertEquals("Hello Android", text.getText().toString());

Log.v("testActivity", "test the Activity Over");

}

// 模拟按钮点击的接口

private class PerformClick implements Runnable {

Button btn = null;

public PerformClick(Button button) {

btn = button;

}

public void run() {

btn.performClick();

}

}

// 测试add方法

public void testAdd() throws Exception{

Log.v("testAdd", "test the add method");

int test = sample.add(1, 1);

assertEquals(2, test);

Log.v("testAdd", "test the add method over");

}

}

    步骤3:修改AndroidManifest.xml文件


<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

package="com.zeroone.unittest"

android:versionCode="1"

android:versionName="1.0" >

<uses-sdk

android:minSdkVersion="8"

android:targetSdkVersion="18" />

<uses-permission android:name="android.permission.INTERNET"></uses-permission>

<application

android:allowBackup="true"

android:icon="@drawable/ic_launcher"

android:label="@string/app_name"

android:theme="@style/AppTheme" >

<uses-library android:name="android.test.runner" />

<activity

android:name="com.zeroone.unittest.Sample"

android:label="@string/app_name" >

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

</application>

<instrumentation android:targetPackage="com.zeroone.unittest"

android:name="android.test.InstrumentationTestRunner"

android:label="Tests for TT
application."
/>

</manifest>

注意:绿色背景为添加部分。其中android:label="Tests
for TT application."
在模拟器中的Dev Tools工具中,设置Instrumentation下显示的名称,在步骤4运行中,点击该标签,也可运行单元测试。在TT Android JUnit Test中也是重要一步,可以设置多个单元,多个名称,每个名称尽量不要重复,以区分不同的单元测试。

步骤4:运行测试类

运行测试类有三种方式,包括:

1、 命令行方式

使用adb命令启动单元测试

2、 eclipse中选择Android JUnit Test运行方式

在eclipse中,右击测试工程,选择run as -> Android JUnit Test

3、 模拟器中,使用Dev Tools

在模拟器中安装该程序后,在Dev Tools工具中,选择Instrumentation下显示的与android:label同名的标签运行单元测试。

2、TT单元测试的编写

要使用TT进行单元测试类的编写,需要将所有的测试类写到一个单独的文件夹下,在进行编译工程时,使用参数-filter将其从编译路径中排除,不对其进行插桩。如下图所示:

被测源码放在src文件夹中,单元测试驱动代码放在test_src文件下。

其他方面,需要在Android单元测试上进行的修改为:

1、引入TT Android jar包,JavaParser-Android.jar

2、将继承Android JUnit Test类换成继承TT Android JUnit Test类,TT Android JUnit Test类中与Android JUnit Test相对应的类为在类名前加TT。例如与InstrumentationTestCase相对应的类为TTInstrumentationTestCase,类所在的包为tt.android.test。

3、在重载了setUp和tearDown函数的测试类中,需要分别调用super.setUp()和super.tearDown()函数。

4、其他操作同Android JUnit
Test操作相同。

如下为一个与上面Android JUnit Test单元测试类相对应的TT Android JUnit Test单元测试类:


package com.zeroone.unittest.test;

import tt.android.test.TTInstrumentationTestCase;

import com.zeroone.unittest.R;

import com.zeroone.unittest.Sample;

import android.content.Intent;

import android.os.SystemClock;

import android.util.Log;

import android.widget.Button;

import android.widget.TextView;

public class SampleTest extends TTInstrumentationTestCase {

private Sample sample = null;

private Button button = null;

private TextView text = null;

// 初始设置

@Override

protected void setUp()  {

try {

super.setUp();

} catch (Exception e) {

e.printStackTrace();

}

Intent intent = new Intent();

intent.setClassName("com.zeroone.unittest", Sample.class.getName());

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

sample = (Sample) getInstrumentation().startActivitySync(intent);

text = (TextView) sample.findViewById(R.id.text1);

button = (Button) sample.findViewById(R.id.button1);

}

// 垃圾清理与资源回收

@Override

protected void tearDown()  {

sample.finish();

try {

super.tearDown();

} catch (Exception e) {

e.printStackTrace();

}

}

// 活动功能测试

public void testActivity() throws Exception {

Log.v("testActivity", "test the Activity");

SystemClock.sleep(1000);

getInstrumentation().runOnMainSync(new PerformClick(button));

SystemClock.sleep(1000);

assertEquals("Hello Android", text.getText().toString());

Log.v("testActivity", "test the Activity Over");

}

// 模拟按钮点击的接口

private class PerformClick implements Runnable {

Button btn = null;

public PerformClick(Button button) {

btn = button;

}

public void run() {

btn.performClick();

}

}

// 测试add方法

public void testAdd() throws Exception{

Log.v("testAdd", "test the add method");

int test = sample.add(1, 1);

assertEquals(2, test);

Log.v("testAdd", "test the add method over");

}

}

3、TT单元测试的编译

编写完成TT Android JUnit Test 测试类之后,使用TT对工程进行编译。

1、修改编译文件,如果是单编码格式的工程,需要修改ant-build-a/android-instru_en.xml文件,多源码格式工程修改ant-build-a/android-instru_code_en.xml文件。修改内容为,添加-filter参数,修改方法为:

添加filterpath属性,用于过滤不需要插桩的单元测试驱动类文件。

<property location="不需要插桩编译的路径"
name="filterpath"/>

<arg
line="&quot;${propath}&quot; &quot;${TT}&quot;
-tt=&quot;${testpropath}&quot; -encoding=${encoding} -filter=&quot;${filterpath}&quot;
-s=&quot;${testpropath}/src&quot;"/>

在运行JavaParser处,添加绿色背景参数。

2、打开TT,创建一个新的工程,与非单元测试工程的编译相同。

4、TT单元测试的运行

将上一步中,TT编译生成的APK文件,安装到模拟器中,安装之后,会在Dev Tools工具下,Instrumentation中会出现与AndroidManifest.xml文件中android:label设置的同名的标签,点击可运行TT单元测试。

在运行TT单元测试时,需要打开TT接收数据,否则测试会阻塞在消息发送处而无法进行。

测试步骤为:

1、打开TT,选择将要运行的测试的工程,然后打开试试监控界面,新建一个测试用例。

2、打开模拟器。

3、进行端口重定向

双击运行adb-android.bat,模拟器打开后,只需运行一次,adb需要在环境变量中配置好,如果未配置,需要手动打开命令行窗口,运行:

adb forward tcp:15555 tcp:15555

adb forward tcp:15556 tcp:15556

adb forward tcp:15557 tcp:15557

adb forward tcp:15558 tcp:15558

如果运行adb forward –list出现:

其中,emulator-5554也可能是其他名称,则说明配置成功。

4、勾选上测试用例,set Ip为127.0.0.1,确定后点击开始。

5、在模拟器中打开Dev Tools,点击Instrumentation进入,点击工程中设置的标签名,如Tests for TT application.

点击后,开始运行运行单元测试。

此时TT实时监控界面会有数据的接收:

单元测试运行运行结束后,右击测试用例树右上角的刷新按钮,选择Update Testcase

会增加红色框中的测试用例,首先是与勾选的测试用例同级同名的测试类型,然后依次为测试类所在的包名,类名以及运行测试函数名。

在单元测试开始之前,被测程序的初始化数据会被保存在初始勾选的测试用例中,这里为UnitTest中。单元测试开始之后,产生的测试数据会被保存到,与测试驱动函数对应的测试用例当中。

TT单元测试完成。

时间: 2024-10-03 21:53:38

安卓应用单元测试技术分享的相关文章

走近支付宝移动支付测试,了解思科安卓先进测试技术,与讯飞人共舞。

走近支付宝移动支付测试,了解思科安卓先进测试技术,与讯飞人共舞.还在等什么?!!!赶快加入讯飞测试技术嘉年华(报名地址: http://itest.iflytesting.com/).前20名报名者将有机会获得精美礼品,并且有机会与来自支付宝.思科的嘉宾进行face to face的交流.时不我待,快快打开你的IE.火狐.chrome.先到既是赚到.如果您愿意前来分享您的经验.您的技术,那么我们也欢迎您到这个舞台来一场个人秀(提交主题地址: http://itest.iflytesting.co

爱奇艺技术分享:爱奇艺Android客户端启动速度优化实践总结

本文由爱奇艺技术团队原创分享,原题<爱奇艺Android客户端启动优化与分析>. 1.引言 互联网领域里有个八秒定律,如果网页打开时间超过8秒,便会有超过70%的用户放弃等待,对Android APP而言,要求更加严格,如果系统无响应时间超过5秒,便会出现ANR,APP可能会被强制关闭,因此,启动时间作为一个重要的性能指标,关系着用户的第一体验. 爱奇艺安卓APP非常重视启动速度的优化,本文将从启动过程.启动时间测量.启动优化.以及后续监控等方面分享我们在启动优化方面积累的经验. 相关文章:

感知开源的力量-APICloud Studio开源技术分享会

2014.9.15 中国领先的"云端一体"移动应用云服务提供商APICloud正式发布 2015.9.15,APICloud上线一周年,迎来第一个生日 这一天,APICloud 举办APICloud Studio开源技术分享会 我们将对APICloud Studio进行技术开源的全面解析, APICloud Studio遵循Aptana3.0 GPL开源协议,源代码以无条件继承GPL开源协议的方式贡献给业界. 我们相信,通过开源技术分享,我们将和广大开发者一起,不断扩展主流HTML开发

Coding for Speed 技术分享

上周和公司技术同事们作了次<Coding for Speed>技术分享,本来这只是再普通不过的技术探讨和交流(虽然挂了个颇有噱头的名称),但分享的时候逻辑没理好,语速很快,时间也太紧,因此难言是合格的"分享"."探讨",所以我觉得有必要以简短的文章形式对原 PPT 作点补充,即便分享的内容很少也很简单. 本文将按原 PPT 的内容顺序分别作扩展说明或阐述,部分敏感信息将隐去,或只会简单提及. 作本技术分享的初衷,一是在工作中了解及接触了一些我个人认为可优

技术分享(持续更新)

这次的技术分享跟大家介绍一个出现在Tinder and Potluck中的动画效果实现思路,最贴心的是作者提供了OC和Swift两个版本来供开发者使用. OC:https://github.com/zhxnlai/ZLSwipeableView, Swift:https://github.com/zhxnlai/ZLSwipeableViewSwift 非常丝滑顺畅的效果,童鞋们都来上手实践一下吧~

尖峰7月线上技术分享--Hadoop、MySQL

7月2号晚20:30-22:30 东大博士Dasight分享主题<大数据与Hadoop漫谈> 7月5号晚20:30-22:30  原支付宝MySQL首席DBA分享主题<MySQL发展趋势,MySQL各个分支介绍>.<MySQL 5.6版本特性介绍及如何从MySQL 5.5向MySQL 5.6> 7月10号晚20:30-22:30 东大博士Dasight分享主题<Hadoop与Nosql技术的适用性分析> 7月12号晚20:30-22:30  原支付宝MySQ

安卓推送技术方案实现探讨

背景介绍 随着苹果产品的风靡,推送技术在国内也越来越热门.推送最开始用于邮件系统.随着iPhone 和 Android 手机的风靡,逐渐在手机上也越来越常见.不少手机客户端也时常推送一些消息. 推送技术的应用 推送技术在手机上的应用主要有两块:广告推送.SNS信息推送. l  广告推送:给目前有一定安装量但没有盈利模式的手机应用开发者带来了一定希望,但要注意推送的频度和内容选中,不然会因为推送的东西用户不感兴趣造成打扰. l  SNS信息推送:主要用于QQ空间.人人网.微博和天涯论坛等web2.

GIS技术分享 -- 开篇

本人GIS小生一枚,学习和实践GIS已有一段时间.有一小小的愿望 - 希望能够利用自己从事GIS方面的经历,与大家共勉,让大家认识GIS.了解GIS,最终熟悉GIS技术与未来. 我主要写一些GIS的工程理论和技术,偏开发.现在我想我的线索可能是WebGIS,3DGIS两块内容的分享,所有的内容都会以实际开发一个GIS系统为例,探索相关理论和技术. 声明:本人也是在学习的路上,希望与各位们共同学习,共同进步! GIS技术分享 -- 开篇,布布扣,bubuko.com

【技术分享会】谈谈公司内部的技术分享

这段时间,为了促进程序同事间技术氛围,在公司内部组织开展技术分享会.形式很简单,每周进行一次技术分享:分享人由组员顺序安排:题材不限,可以是自己熟悉的技术,比如说服务端的开发者,分享后端定时器,消息队列等等,前端的开发者分享加载的模式,MVC模式等等,可以是一些通用的技术,比如数据结构,算法,代码风格,Effective 系列,调试技巧等,甚至可以是经典书的读后感等等,抑或是最近大家在研究一个开源的项目,也可以跟大家讲一下这个开源项目的框架:或许有些人利用业余时间做了一个小软件,也可以拿出来分享