安卓006单元测试
来源:互联网 发布:popo聊天软件 编辑:程序博客网 时间:2024/05/18 03:29
Android 测试,日志
测试
常见测试分类在介绍Android Junit前先介绍一下常见的测试分类。
根据是否知道源程序源码:
黑盒测试:不知源码,只是测试程序的功能
白盒测试:知道源码,根据源代码进行测试
根据测试的粒度:(模块的大小)
单元测试:unit test
功能测试:function test:方法测试
整合测试:integration test:几个模块的测试,服务器/客户端的联调
系统测试:system test
根据测试的次数:(暴力测试)
冒烟测试:smoke test,不停的执行操作,直到系统崩溃
Google提供了一个monkey
Adb shell:进入模拟器目录,monkey
2000,通过monkey是随机点击2000次
monkey –p 包名 次数:只测试某个应用程序
压力测试:pressure test
Junit 测试框架
运行测试代码:后台会帮我们做两步操作
上传当前应用程序到手机系统
发送指令通知手机测试刚才上传的代码
所以需要在清单文件里配置:
添加指令集(manifest节点下)
<instrumentation
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.example.sqlitephone" />
targetPackage:是测试目标包
指令集依赖jar包(application节点下)
<uses-library android:name="android.test.runner" />
Junit 测试步骤
单元测试
在实际开发中,开发android软件的过程需要不断地进行测试。而使用Junit 测试框架,则是正规的Android开发的必用技术,Android很好封装了Junit测试框架,可以模拟发送事件和检测程序处理的正确性
* Android单元测试实现流程
1.添加测试类库
在AndroidManifest.xml 的<application> 节点 添加测试类库
<uses-library android:name="android.test.runner"/>
2.设置测试环境
<instrumentationandroid:name="android.test.InstrumentationTestRunner"android:targetPackage="cn.itcast.filestore"/>
3. 编写测试类
- 获取上下文getContext()- 继承AndroidTestCase
- 使用断言 assertEquals()
- 查看测试效果
我们完成了一个业务方法,想要对其进行测试,Android程序是不能写main
方法运行的,需要建测试项目。
1. 创建测试项目
创建测试工程
定义工程名
选择要测试哪个工程
创建测试类,注意要继承AndroidTestCase
编写测试类
可以直接使用被测试工程中的业务类,测试方法必须以小写“test”开头
2. 不创建测试项目,加测试类
在AndroidManifest.xml清单文件中添加配置
< instrumentation android:targetPackage= "cn.itcast.junit"
android:name= "android.test.InstrumentationTestRunner" />
<uses-library android:name= "android.test.runner" />
定义一个类继承AndroidTestCase,定义测试方法
Junit 单元测试
新建业务方法
例如计算器的加法:
// 计算器
public class Calc {
/**
* 计算器相加的方法
* @param x
* @param y
* @return
*/
public int add(int x, int y) {
return x + y;
}
}
新建Junit测试类,对add方法进行单元测试
//Android中想要进行单元测试 需要继承AndroidTestCase
public class TestCalc extends AndroidTestCase{
//需要写一个测试方法
public void testAdd(){
//想测试 计算器相加的方法
Calc calc = new Calc();
int result = calc.add(5, 6);
//断言
assertEquals(11,result);
}
}
在清单文件中添加测试指令
<!--测试需要改成我们自己应用的包 -->
<instrumentation
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.itheima.unit"
android:label="Tests for My App" />
运行测试方法testAdd
如图:双击方法,右键Run As——Android Junit Test
运行结果:绿条代表测试通过。
Junit 单元测试,在公司中会用到,所以大家需要掌握。
Android Junit 拓展知识
注意:拓展知识并不是必须要求掌握的,心有余力之时可以作为进一步提升的
参考。
Android
测试环境的核心是一个Instrumentation框架,在这个框架下,你的测试应用程序
可以精确控制应用程序。使用Instrumentation,
你可以在主程序启动之前,创建模拟的系统对象,如Context;控制应用程序的
多个生命周期;发送UI事件给应用程序;在执行期间检查程序状态。
Instrumentation框架通过将主程序和测试程序运行在同一个进程来实现这些功能
。
通过在测试工程的manifest文件中添
加<instrumentation>元素来指定要测试的应用程序。这个元素的特性指明了要测
试的应用程序包名,以及告诉Android如何运行测试程序。下面的图片概要的描
述了Android的测试环境:
在
Android中,测试程序也是Android程序,因此,它和被测试程序的书写方式有
很多相同的地方。SDK工具能帮助你同时创建主程序工程及它的测试工程。你
可以通过Eclipse的ADT插件或者命令行来运行Android测试。Eclipse的ADT提供
了大量的工具来创建测试用例,运行以及查看结果。
Android提供了基于JUnit测试框架的测试API来书写测试用例和测试程序。
另外,Android还提供了强大的Instrumentation框架,允许测试用例访问程序的
状态及运行时对象。
Android Junit 中的主要核心API
JUnit TestCase类
继承自JUnit的TestCase,不能使用Instrumentation框架。但这些类包含
访问系统对象(如Context)的方法。使用
Context,你可以浏览资源,文件,数据库等等。基类是AndroidTestCase,一
般常见的是它的子类,和特定组件关联。
子类有:
ApplicationTestCase——
测试整个应用程序的类。它允许你注入一个模拟的Context到应用程
序中,在应用程序启动之前初始化测试参数,并在应用程序结束之
后销毁之前检查应用程序。
ProviderTestCase2——
测试单个ContentProvider的类。因为它要求使用MockContentResolve
r,并注入一个IsolatedContext,因此Provider的测试是与OS孤立的
。
ServiceTestCase——
测试单个Service的类。你可以注入一个模拟的Context或模拟的Appl
ication(或者两者),或者让Android为你提供Context和MockApplic
ation。
Instrumentation TestCase类
继承自JUnit
TestCase类,并可以使用Instrumentation框架,用于测试Activity。使用Instrument
ation,Android可
以向程序发送事件来自动进行UI测试,并可以精确控制Activity的启动,监测Ac
tivity生命周期的状态。
基类是InstrumentationTestCase。它的所有子类都能发送按键或触摸事件
给UI。子类还可以注入一个模拟的Intent。子类有:
ActivityTestCase——Activity测试类的基类。
SingleLaunchActivityTestCase——
测试单个Activity的类。它能触发一次setup()和tearDown(),而不是
每个方法调用时都触发。如果你的测试方法都是针对同一个Activity
的话,那就使用它吧。
黑马Android课程笔记 就业服务部出品
SyncBaseInstrumentation——测试Content
Provider同步性的类。它使用Instrumentation在启动测试同步性之前
取消已经存在的同步对象。
ActivityUnitTestCase——
对单个Activity进行单一测试的类。使用它,你可以注入模拟的Cont
ext或Application,或者两者。它用于对Activity进行单元测试。不同
于其它的Instrumentation类,这个测试类不能注入模拟的Intent。
ActivityInstrumentationTestCase2——
在正常的系统环境中测试单个Activity的类。你不能注入一个模拟的
Context,但你可以注入一个模拟的Intent。另外,你还可以在UI线
程(应用程序的主线程)运行测试方法,并且可以给应用程序UI发
送按键及触 摸事件。
Assert类
Android还继承了JUnit的Assert类,其中,有两个子类,MoreAsserts和Vi
ewAsserts。
MoreAsserts类包含更多强大的断言方法,如assertContainsRegex(Stri
ng, String),可以作正则表达式的匹配。
ViewAsserts类包含关于Android
View的有用断言方法,如assertHasScreenCoordinates(View, View,
int,
int),可以测试View在可视区域的特定X、Y位置。这些Assert简化
了UI中几何图形和对齐方式的测试。
Mock对象类
Android
有一些类可以方便的创建模拟的系统对象,如Application,Context,Content
Resolver和Resource。Android还在一些测试类中提供了一些方法来创建模拟的In
tent。因为这些模拟的对象比实际对象更容易使
用,因此,使用它们能简化依赖注入。你可以在android.test和android.test.mock
中找到这些类。
它们是:
IsolatedContext——
模拟一个Context,这样应用程序可以孤立运行。与此同时,还有大
量的代码帮助我们完成与Context的通信。这个类在单元测试时很有
用。
黑马Android课程笔记 就业服务部出品
RenamingDelegatingContext——
当修改默认的文件和数据库名时,可以委托大多数的函数到一个存
在的、常规的Context上。使用这个类来测试文件和数据库与正常的
系统Context之间的操作。
MockApplication,MockContentResolver,MockContext,MockDialogInter
face,MockPackageManager,MockResources ——
创建模拟的系统对象的类。它们只暴露那些对对象的管理有用的方
法。这些方法的默认实现只是抛出异常。你需要继承这些类并重写
这些方法。
Instrumentation TestRunner
Android
提供了自定义的运行测试用例的类,叫做InstrumentationTestRunner。这个类控
制应用程序处于测试环境中,在同一个进程中运行测试
程序和主程序,并且将测试结果输出到合适的地方。IntrumentationTestRunner
在运行时对整个测试环境的控制能力的关键是使用
Instrumentation。注意,如果你的测试类不使用Instrumentation的话,你也可以
使用这个TestRunner。
当你运行一个测试程序时,首先会运行一个系统工具叫做Activity
Manager。Activity
Manager使用Instrumentation框架来启动和控制TestRunner,这个TestRunner反过
来又使用
Intrumentation来关闭任何主程序的实例,然后启动测试程序及主程序(同一个
进程中)。这就能确保测试程序与主程序间的直接交互。
在测试环境中工作
对Android程序的测试都包含在一个测试程序里,它本身也是一个Android
应用程序。测试程序以单独的Android工程存在,与正常的Android程序有着相
同的文件和文件夹。测试工程通过在manifest文件中指定要测试的应用程序。
每个测试程序包含一个或多个针对特定类型组件的测试用例。测试用例里
定义了测试应用程序某些部分的测试方法。当你运行测试程序,Android会在相
同进程里加载主程序,然后触发每个测试用例里的测试方法。
测试工程
为了开始对一个Android程序测试,你需要使用Android工具创建一个测试
工程。工具会创建工程文件夹、文件和所需的子文件夹。工具还会创建一个ma
nifest文件,指定被测试的应用程序。
黑马Android课程笔记 就业服务部出品
测试用例
一个测试程序包含一个或多个测试用例,它们都继承自Android
TestCase类。选择一个测试用例类取决于你要测试的Android组件的类型以及你
要做什么样的测试。一个测试程序可以测试不同的组件,但每个测试用例类设
计时只能测试单一类型的组件。
一些Android组件有多个关联的测试用例类。在这种情况下,在可选择的
类间,你需要判断你要进行的测试类型。例如,对于Activity来说,你有两个选
择,ActivityInstrumentationTestCase2和ActivityUnitTestCase。
ActivityInstrumentationTestCase2设计用于进行一些功能性的测试,因此
,它在一个正常的系统环境中测试Activity。你可以注入模拟的Intent,但不能
是模拟的Context。一般来说,你不能模拟Activity间的依赖关系。相比而言,A
ctivityUnitTestCase设计用于单元测试,因此,它在一个孤立的系统环境中测试
Activity。换句话说,当你使用这个测试类时,Activity不能与其它Activity交互
。
作为一个经验法则,如果你想测试Activity与Android的交互的话,使用Acti
vityInstrumentationTestCase2。如果你想对一个Activity做回归测试的话,使用Ac
tivityUnitTestCase。
测试方法
每个测试用例类提供了可以建立测试环境和控制应用程序的方法。例如,
所有的测试用例类都提供了JUnit的setUp()方法来搭建测试环境。另外,你可以
添加方法来定义单独的测试。当你运行测试程序时,每个添加的方法都会运行
一次。如果你重写了setUp()方法,它会在每个方法运行前运行。相似
的,tearDown()方法会在每个方法之后运行。
测试用例类提供了大量的对组件启动和停止控制的方法。由于这个原因,
在运行测试之
前,你需要明确告诉Android启动一个组件。例如,你可以使用getActivity()来启
动一个Activity。在整个测试用例期间,你只能调
用这个方法一次,或者每个测试方法一次。甚至你可以在单个测试方法中,调
用它的finishing()来销毁Activity,然后再调用 getActivity()重新启动一个。
运行测试并查看结果
编译完测试工程后,你就可以使用系统工具Activity
Manager来运行测试程序。你给Activity
Manager提供了TestRunner的名(一般是InstrumentationTestRunner,在程序中指
定);名包括被测试程序的包名和 TestRunner的名。Activity
Manager加载并启动你的测试程序,杀死主程序的任何实例,然后在测试程序的
同一个进程里加载主程序,然后传递测试程序的第一个测试用例。这个时
候,TestRunner会接管这些测试用例,运行里面的每个测试方法,直到所有的
方法运行结束。
黑马Android课程笔记 就业服务部出品
如果你使用Eclipse,结果会在JUnit的面板中显示。如果你使用命令行,
将输出到STDOUT上。
测试什么?
除了一些功能测试外,这里还有一些你应该考虑测试的内容:
Activity生命周期事件:你应该测试Activity处理生命周期事件的正确性。例如,
一个Activity应该在pause或destroy事件
时保存它的状态。记住一点的是屏幕方向的改变也会引发当前Activity销毁,因
此,你需要测试这种偶然情况确保不会丢失应用程序状态。
数据库操作:你应该确保数据库操作能正确处理应用程序状态的变化。使用and
roid.test.mock中的模拟对象。
屏幕大小和分辨率:在发布程序之前,确保在所有要运行的屏幕大小和分辨率
上测试通过。你可以使用AVD来测试,或者使用真实的目标设备进行测试。
UI 线程中测试
Activity运行在程序的UI线程里。一旦UI初始化后,例如在Activity的onCrea
te()方法后,所有与UI的交互都必须运行在UI线程里。当你正常运行程序时,它
有权限可以访问这个线程,并且不会出现什么特别的事情。当你运行测试程序
时,这一点发生了变化。在带有instrumentation的类里,你可以触发方法在UI线
程里运行。其它的测试用例类不允许这么做。
为了一个完整的测试方法都在UI线程里运行,你可以使用@UIThreadTest来
声明线程。注意,这将会在UI线程里运行方法里所有的语句。不与UI交
互的方法不允许这么做;例如,你不能触发Instrumentation.waitForIdleSync()。
如果让方法中的一部分代码运行在UI线程的话,创建一个匿名的Runnabl
e对象,把代码放到run()方法中,然后把这个对象传递给appActivity.runOnUiThr
ead(),在这里,appActivity就是你要测试的app对象。
日志信息
LogCat 介绍
Android
LogCat的获取有两种方式:1、DDMS提供的LogCat视图2、通过adb命令行
DDMS提供的LogCat视图如下
如果该视图没有打开,点击window->show view->other->android-
>Logcat来进行选择。
视图的左侧可以选择或者添加过滤信息,运行一个应用程序时,此处会默
认创建一个该包的过滤。视图的右上角区域用于选择LogCat的log级别,共有ver
bose、debug、info、warn、error、assert6个可选项。如图所示:
。
该视图的主体部分是log的详细信息,包括错误级别(Level)、时间(Tim
e)、进程ID(PID)、线程ID(TID)、应用程序包名(Application)、标签(
Tag)、日志正文(Text)。
其中的TID并不等同于Java中的Thread.currentThread().getId(),而是我们Linux
中的Thread ID,跟PID相同。
通过命令行调用LogCat
将LogCat信息显示在控制台中
在控制台中输入adb logcat
然后按回车键即可看到LogCat信息,如果需要终止按Ctrl+C键即可。
将LogCat信息保存在文件中
执行adb logcat >D:/a.txt
则将日志输出到D:/a.txt文件中。按Ctrl+C键终止日志的输出。
上面介绍的只是adb
logcat命令的最简单用法,其实该命令还有多种可选参数供选择,这里就不再详
细说明。
Logcat 的日志等级
android.util.Log常用的方法有以下5个:
Log.v() Log.d() Log.i() Log.w() 以及 Log.e() 。根据首字母对应VERBOSE
,DEBUG,INFO, WARN ,ERROR。
Log.v
的调试颜色为 黑色的,任何消息都会输出,这里的v代表verbose啰嗦的意思
,平时使用就是Log.v("","");
Log.d的输出颜色是 蓝色的,仅输出debug调试的意思,但他会输出上层的信
息,过滤起来可以通过DDMS的Logcat标签来选择.
Log.i的输出为 绿色,一般提示性的消息information,它不会输出Log.v和Log
.d的信息,但会显示i、w和e的信息,System.out输出信息是Info级别
Log.w的意思为 橙色,可以看作为warning警告,一般需要我们注意优化And
roid代码,同时选择它后还会输出Log.e的信息。
Log.e为红色,可以想到error错误,这里仅显示红色的错误信息,这些错误
就需要我们认真的分析,查看栈的信息了。
程序中我们可以使用Log类来输出信息
结果:
Logcat 通过tag 过滤
tag:可以利用tag进行过滤,用于查找日志。
在logcat中可以添加一个日志过滤器,选择日志等级,会显示出当前等级和比当
前等级高的等级。选择warn,会出现warn和error两种日志。还可以使用System.
out来打印日志(info级别),System.error(警告级别)
Logcat 日志激活
激活日志,ddms中随便点击devices中的一项即可。其实日志是打印在模拟器里
的,系统通过adb,将日志信息传递到开发平台的logcat中
如果还是没有打印日志,就重启adb或eclipse,然后也可以通过命令adb
logcat,可在cmd中查看日志
案例-Android 程序获取LogCat 信息
下面通过创建一个Android工程来演示如何在代码中实时获取LogCat信息。
创建一个新工程,这里工程名为LogCat
在这个工程中使用默认的MainActivity.java类和默认的布局文件。
修改布局文件
<LinearLayout
xmlns:android= "http://schemas.android.com/apk/res/android"
xmlns:tools= "http://schemas.android.com/tools"
android:layout_width= "match_parent"
android:layout_height= "match_parent"
android:orientation= "vertical"
tools:context= ".MainActivity" >
<Button
android:layout_width= "wrap_content"
android:layout_height= "wrap_content"
android:text= "获取LogCat"
android:id= "@+id/bt_click"
/>
<TextView
android:id= "@+id/tv_show"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:hint= "显示日志"
/>
</LinearLayout>
修改MainActivity.java代码
代码第一部分:
package com.itheima.com.logcat;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
protected static final String TAG = "MyTest";
private Button btn;
private TextView tv_show;
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
tv_show.setText((String) msg.obj);
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.bt_click);
tv_show = (TextView) findViewById(R.id.tv_show);
黑马Android课程笔记 就业服务部出品
代码第二部分:
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.v(TAG, "这是verbose信息");
Log.d(TAG, "这是debug信息");
Log.i(TAG, "这是info信息");
Log.w(TAG, "这是warn信息");
Log.e(TAG, "这是error信息");
/** 开启线程用于监听log输出的信息 **/
new Thread(new Runnable() {
@Override
public void run() {
Process mLogcatProc = null;
BufferedReader reader = null;
try {
/*
*
通过执行命令行获取LogCat信息
*/
mLogcatProc =
Runtime.getRuntime().exec(new String[] { "logcat", TAG + ":v *:s"
});
/*
* 获取进程输出流对象
*/
reader = new
BufferedReader(new
InputStreamReader(mLogcatProc.getInputStream()));
String line = null;
StringBuilder sb = new
StringBuilder();
代码第三部分(完):
while ((line = reader.readLine()) != null) {
sb.append(line);
Message msg =
Message.obtain();
msg.obj =
sb.toString();
handler.sendMessage(msg);
}
reader.close();
/*
*
通过发送消息,通知主线程修改TextView对象
*
因此这个操作是在子线程中进行的,而Android应用中子线程是无法修改UI(UI的修改
操作必须在
* 主线程中进行
*
,因此Android提供了Handler机制,让子线程发送消息给主线程,然后由主线程修改U
I).
*/
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
});
}
}
将项目运行在模拟器上,并点击按钮
运行结果如图所示:
结合工作和面试
面试中
Junit测试
面试中有可能会被问到,你们公司以前是怎么去测试的?
你可以说我们公司比较规范,有的功能会用Junit测试。也可以说,
我们就是手工测试,自己测试没问题了,提交给测试人员去测试。
然后他们提交bug,我们修复。
日志信息
面试中,会被问到,你是怎么解决bug的?
一般说下,断点调试,变量分析,日志跟踪即可。
变量分析就是断点调试过程中,对变量的值进行监控,看是否为null
,或者不正常。
工作中
Junit测试
这个会使用即可,一般的小公司不会让做Junit测试,就是手测。大
公司,制度比较严格的可能会要求做Junit测试。要做也是一般的单
元测试,所以大家单元测试需要掌握。
主要还是测试人员写测试用例去测。
日志信息
上边也提到过了,这个比较重要,一定要会看日志信息,对代码分
析,bug调试很有帮助。
还有就是有些同学的日志有时候出现不了,参照Logcat日志激活,
一般就是设备没连接成功,连接后有可能需要选择一下连接的设备
。
- 安卓006单元测试
- 安卓单元测试InstrumentationTestRunner
- 安卓单元测试
- 安卓单元测试
- 安卓单元测试全攻略
- (1) Android Junit 安卓单元测试
- 安卓自动化测试及单元测试
- XML解析和安卓单元测试框架
- 安卓复习1-安卓基础-单元测试
- 安卓自动化测试入门-3-网络请求的单元测试
- 安卓自动化测试入门-4-Presenter的单元测试
- 安卓单元测试全攻略,让代码测试一劳永逸
- 安卓单元测试全攻略,让代码测试一劳永逸
- 安卓开发-尺寸单位+Logcat的使用+Android单元测试+安卓系统中数据的读写
- 安卓单元测试错误Test run failed: Unable to find instrumentation target package解决办法
- About Unit Test In Android(安卓单元测试研究,附技术分享ppt)
- 【腾讯Bugly干货分享】安卓单元测试:What, Why and How
- 利用Instrumentation单元测试模块控制安卓手机进行各项操作(微信)
- Ubuntu Server 13.10安装配置图解教程
- 分布式架构高可用架构篇_01_zookeeper集群的安装、配置、高可用测试
- 翻译_Understanding JSON(理解json)
- Intuition of Back Propogation&Sparse Autoencoder
- Jackson学习笔记(一)
- 安卓006单元测试
- Leetcode no. 52
- MySQL数据库引擎详解
- 模仿音乐播放器项目
- 数据挖掘基本知识框架
- 初识html5基本格式
- 笔试题24. LeetCode OJ (11)
- vs2010删除类
- 判断大端还是小端