您的位置:首页 > 移动开发 > Android开发

Android开发---测试教程

2015-10-30 15:27 471 查看

Android中的测试框架

Android测试框架基于JUnit,JUnit是一个开放源代码的Java测试框架,用于编写和运行可重复的测试。尽管你可以使用JUnit测试Android工程,但Android工具允许你为应用程序的各个方面进行更为复杂的测试,包括单元层面及框架层面。

Android JUint 扩展提供了对Android特定组件(如Activity,Service)的测试支持,这些扩展类提供了一些辅助方法来帮助创建测试使用的“桩”类或方法。

Test case 相关类

Android提供了多个由Testcase或Assert派生而来的子类以支持Android平台相关的setup,teardown 和其它辅助方法。

AndroidTestCase 为一Android平台下通用的测试类,它支持所有JUnit的Assert方法和标准的setUp 和tearDown 方法,并可以用来测试Android permission 。组件相关的测试类如测试activity,Contentprovider,Service相关的测试类Android没有提供单独的用来测试BroadcastReceiver的测试类,而是可以通过发送Intent对象来检测BroadcastReceiver的反应结果来测试BroadcastReceiver。ApplicationTestCase 可以用来测试Application 对象。

InstrumentationTestCase 如果你要使用Instrumentation API,那么你必须使用InstrumentationTestCase或其子类。

Assertion classes

Android测试中可以使用JUnit中提供的Assert方法来显示测试结果。除此之外,Testing API还提供了MoreAsserts 和ViewAsserts 类。其中MoreAsserts支持更多的比较方法包括RegEx(正则)比较等。ViewAsserts 可以用来校验UI View。

Mock object classes

android.test.mock包中定义一些测试“桩”类,如MockApplication,MockContentProvider,MockContext,MockCursor, MockPackagManager等用例帮助测试。

JUnit单元测试

什么是单元测试

单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。单元测试不是为了证明是对的,而是为了证明没有错误。元测试主要是用来判断程序的执行结果与自己期望的结果是否一致。关键是在于所用的测试用例(Test Case) 。

JUnit的使用

首先编写一个待测试类Calculator

package com.mengdd.junit;

public class Calculator
{
public int add(int a, int b)
{
return a + b;
}

public int subtract(int a, int b)
{
return a - b;
}

public int multiply(int a, int b)
{
return a * b;
}

public int divide(int a, int b)
{
return a / b;
}
}


再编写一个测试类

测试类的要求:

public abstract class TestCase extends Assert implements Test

A test case defines the fixture to run multiple tests.

To define a test case

1) implement a subclass of TestCase

2) define instance variables that store the state of the fixture

3) initialize the fixture state by overriding setUp

4) clean-up after a test by overriding tearDown.

Each test runs in its own fixture so there can be no side effects among test runs.

上面的官方文档中的编写测试类的要求

1. 必须继承于TestCase 可以看到的是这个类继承于Assert 实现了Test接口

2. 定义存储设备状态的实例变量、

3. 在重写的setUp方法中去初始化这个实例变量

4. 在重写的tearDown方法中去销毁这个实例变量

并且所有的TestCase之间不能有任何的关联

并且在每个测试类中的测试方法必须满足:

1.访问权限必须是public的

2.返回值是void的

3.不带参数

4.方法名称必须以test开头。 (它通过反射找出所有方法,然后找出以test开头的方法)。

下面看一个例子:

import junit.framework.Assert;
import junit.framework.TestCase;

public class CalculatorTest extends TestCase
{
public void testAdd()
{
Calculator calculator = new Calculator();
int result = calculator.add(1, 2);
// 判断方法的返回结果
Assert.assertEquals(3, result);// 第一个参数是期望值,第二个参数是要验证的值
}

public void testSubtract()
{
Calculator calculator = new Calculator();
int result = calculator.subtract(1, 2);
// 判断方法的返回结果
Assert.assertEquals(-1, result);// 第一个参数是期望值,第二个参数是要验证的值

}

public void testMultiply()
{
Calculator calculator = new Calculator();
int result = calculator.multiply(2, 3);
// 判断方法的返回结果
Assert.assertEquals(6, result);// 第一个参数是期望值,第二个参数是要验证的值

}

public void testDivide()
{
Calculator calculator = new Calculator();
int result = calculator.divide(12, 3);
// 判断方法的返回结果
Assert.assertEquals(4, result);// 第一个参数是期望值,第二个参数是要验证的值
}
}


在测试类中还有两个重要的方法:

1)setUp方法是在执行每个测试方法之前执行的

2)testDown方法是在执行每个测试方法之后执行的

下面看一下Assert类的使用:

1.assertTrue/False([String message,]boolean condition);

判断一个条件是true还是false。感觉这个最好用了,不用记下来那么多的方法名。

2.fail([String message,]);

失败,可以有消息,也可以没有消息。

3.assertEquals([String message,]Object expected,Object actual);

判断是否相等,可以指定输出错误信息。

第一个参数是期望值,第二个参数是实际的值。

这个方法对各个变量有多种实现。在JDK1.5中基本一样。

但是需要主意的是float和double最后面多一个delta的值。

4.assertNotNull/Null([String message,]Object obj);

判读一个对象是否非空(非空)。

5.assertSame/NotSame([String message,]Object expected,Object actual);

判断两个对象是否指向同一个对象。看内存地址。

7.failNotSame/failNotEquals(String message, Object expected, Object actual)

当不指向同一个内存地址或者不相等的时候,输出错误信息。

注意信息是必须的,而且这个输出是格式化过的。

Activity测试

Activity的测试依赖于Android的Instrumation 框架,

测试Activity的基本测试类为InstrumentationTestCase,它提供了Instrumentation接口给TestCase的子类。 InstrumentationTestCase提供了下面功能:

生命周期控制: 使用Instrumentation,你可以启动,暂停,中止被测试的Activity。

Dependency Injection : Instrumentation允许创建一些Mock对象如Context,Application来帮助测试Activity,从而帮助你控制测试环境并和实际的应用的其他部分隔离开来。你也可以定制一些Intent以启动Activity。

用户界面交互: 你可以使用Instrumentation向UI发送按键和触摸事件。

下面几个为主要的用于测试Activity由TestCase派生而来的测试类:

ActivityInstrumentationTestCase2 提供了下面功能:

通常用于多个Activity的功能测试,它使用正常的系统框架来运行Activity(使用应用程序本身),并使用正常系统Context (非Mock)来测试Activity的功能。 允许你创建一些Mock Intent 用来测试Activity的响应。要注意的是,这种TestCase不允许使用Mock的Context和Application对象测试,也就是说你必须使用和应用程序实际运行的环境来测试。

ActivityUnitTestCase 提供了下面功能:

通常用来测试单独Activity。在启动被测试的Activity之前,你可以Inject一个假的Context或是Application ,使用这个Mock的Context中一个隔离环境中运行被测试的Activity。通常用于Activity的单元测试,而不和Anroid系统进行交互。

SingleLaunchActivityTestCase 提供了下面功能:

用于测试单个Activity,和ActivityUnitTestCase不同的是,它只运行setUp 和tearDown 一次,而不是在运行testCase 中每个Test Method前后运行setup 和tearDown ,它可以保证运行多个测试之间fixture 不会被重置,从而可以用来测试一些有关联的方法。

Content Provider测试

Android 测试包中用于测试Content Provider的基本类为ProviderTestCase2

ActivityUnitTestCase 提供了下面功能:

允许你在一个隔离环境下来测试Content Provider。 并提供了一些Mock类如IsolatedContext ,MockContentResover 来辅助测试。和其它测试一样,对于Content Provider测试也是通过InstrumentationTestRunner 来进行的。

编译测试代码的一般方法是通过派生ProviderTestCase2 (为AndroidTestCase 的子类),因此可以使用JUnit和Android平台相关的方法来测试Content Provider。

Service测试

Android 测试框架也提供对Service测试的支持,基本类为ServiceTestCase,因为Service类通常假定和它是和Client是分开使用的,因此你可以无需使用Instrumentation 来测试Service。

ServiceTestCase 提供了下面功能:

可以取得当前被测试的Service对象。

ServiceTestCase 为AndroidTestCase的子类,因此可以测试和Permission 相关的功能,并提供Mock的Application 和Context 对象为测试Service提供了一个隔离的测试环境。

ApplicationTestCase的使用

继承于AndroidTestCase

下面看下公共方法:

public T getApplication ()

返回值:

Returns the actual Application under test.

public Context getSystemContext ()

Return a real (not mocked or instrumented) system Context that can be used when generating Mock or other Context objects for your Application under test.

返回值:

Returns a reference to a normal Context.

public final void testApplicationTestCaseSetUpProperly ()

This test simply confirms that the Application class can be instantiated properly.

首先可以实现一个自己的Application 类:

import android.app.Application;

public class FxAndroidApplication extends Application
{
@Override
public void onCreate()
{
// TODO Auto-generated method stub
super.onCreate();
}

@Override
public void onTerminate()
{
// TODO Auto-generated method stub
super.onTerminate();
}

public String getFavourite()
{
return "I Love Java";
}
}


记住在manifest中注册这个Application类

给一个ApplicationTestCase的模拟实现:

import com.phicomm.hu.FxAndroidApplication;

import android.app.Application;
import android.test.ApplicationTestCase;

public class FxApplicationTest extends ApplicationTestCase<FxAndroidApplication>
{

private FxAndroidApplication AppTest;
public FxApplicationTest()
{
//调用父类构造函数,且构造函中传递的参数为被测试的类
super(FxAndroidApplication.class);
}

@Override
protected void setUp() throws Exception
{
// TODO Auto-generated method stub
super.setUp();
//获取application之前必须调用的方法
createApplication();
//获取待测试的FxAndroidApplication
AppTest = getApplication();
}

//测试FxAndroidApplication的getFavourite方法
public void testGetFavourite()
{
/*验证预测值"I Love C++"是否等于实际值,
由于实际值为"I love Java",所以此处测试结果为Failure*/
assertEquals("I Love C++", AppTest.getFavourite());
}

}


在这个TestCase中我们采用了ApplicationTestCase的共有方法getApplication获得这个Application的对象,但是记得首先调用createApplication创建一个Application。

ActivityInstrumentationTestCase2的使用

ActivityInstrumentationTestCase2 主要用来测试一个或多个Activity的功能测试,使用和最终应用同样的运行环境来测试Activity的功能。可以使用正常系统Context (非Mock)来测试Activity的功能。 并允许你创建一些Mock Intent 用来测试Activity的响应。要注意的是,这种TestCase不允许使用Mock的Context和Application对象测试,也就是说你必须使用和应用程序实际运行的环境来测试。

下面看下公共方法:

T getActivity()

Get the Activity under test, starting it if necessary.

void setActivityInitialTouchMode(boolean initialTouchMode)

Call this method before the first call to getActivity() to set the initial touch mode for the Activity under test.

在启动Activity之前设置TouchMode

void setActivityIntent(Intent i)

Call this method before the first call to getActivity() to inject a customized Intent into the Activity under test.

可以设置启动Activity的Intent 对象来测试Activity

给一个ActivityInstrumentationTestCase2的模拟实现:

public class ApiDemosTest extends ActivityInstrumentationTestCase2<ApiDemos> {

public ApiDemosTest() {
super(ApiDemos.class);
}

public void testActivityTestCaseSetUpProperly() {
assertNotNull("activity should be launched successfully", getActivity());
}
}


ServiceTestCase 的使用

ServiceTestCase 为测试Service提供了一个可控的测试环境,它提供对Service 生命周期的基本支持,并可以通过注入一些依赖对象来控制测试环境以便测试Service。

下面看下公共方法:

Application getApplication()

Returns the Application object in use by the service under test.

T getService()

Context getSystemContext()

Returns the real system context that is saved by setUp().

void setApplication(Application application)

Sets the application that is used during the test.

void testServiceTestCaseSetUpProperly()

Tests that setupService() runs correctly and issues an assertNotNull(String, Object) if it does.

public class LocalServiceTest extends ServiceTestCase<LocalService> {

public LocalServiceTest() {
super(LocalService.class);
}

@Override
protected void setUp() throws Exception {
super.setUp();
}

@SmallTest
public void testPreconditions() {
}

/**
* Test basic startup/shutdown of Service
*/
@SmallTest
public void testStartable() {
Intent startIntent = new Intent();
startIntent.setClass(getContext(), LocalService.class);
startService(startIntent);
}

/**
* Test binding to service
*/
@MediumTest
public void testBindable() {
Intent startIntent = new Intent();
startIntent.setClass(getContext(), LocalService.class);
IBinder service = bindService(startIntent);
}

}


testStartable 测试对应的Service能否正常启动。

testBindable 测试对应的Service能否绑定成功
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 测试 junit