通过前面2篇文章的学习,我们对JUnit有了初步的认识,下面我们将深入的解析JUnit数据包。整个JUnit的数据包应该是很强大的,但是一般来说,不一定每个工程都需要这些数据包,而是在JUnit部分数据包的基础上扩展出自己的数据包,AndroidSDK中也不例外。至于JUnit完整的包,这里我们就不详细分析了,我们这里只解析AndroidSDK中包含的那些JUnit数据包,以及Android SDK在JUnit的基础上扩展的一些数据包,如下:
SDK | 功能说明 |
junit.framework | JUnit测试框架 |
junit.runner | 实用工具类支持JUnit测试框架 |
android.test | Android 对JUnit测试框架的扩展包 |
android.test.mock | Android的一些辅助类 |
android.test.suitebuilder | 实用工具类,支持类的测试运行 |
1 | 1 |
在这些包中最为重要的是:junit.framework、android.test,其中前者是JUnit的核心包,后者是AndoidSDK在Junit.framework的基础上扩展出来的包,我们将重点解析这2个包。
首先解析junit.framework包,结构如下:
通过这张图,大家就可以比较清晰的看到JUnit的主要框架,再回去看下上篇文章的例子,对前面的例子感觉明白多了。做个简要的总结,如下:
- TestSuit:TestSuite是测试用例的集合;
- TestCase:定义运行多个测试用例;
- TestResult:收集一个测试案例的结果,测试结果分为失败和错误,如果未能预计的断言就是失败,错误就像一个ArrayIndexOutOfBoundsExc
eption异常而导致的无法预料的问题;
- TestFailure:测试失败时捕获的异常;
- Assert:断言的方法集,当断言失败时显示信息;
TestCase与TestSuite之间的关系,有些类似于图元对象与容器对象之间的关系,在面向对象的语言C++、JAVA中较常见,在这里就不多说了。
举个简单的例子,并简要说明过程
第一步:实现TestCase
- 继承父类TestCase;
- 定义一下变量在测试中使用;
- 在setUp()中初始化这些变量;
- 在tearDown()中清理这些变量;
public class MathTest extends TestCase{
protected double fValue1;
protected double fValue2;
protected void setUp(){
fValue1= 2.0;
fValue2= 3.0;
}
}
- 编写测试单元代码;
public void testAdd() {
double result= fValue1 + fValue2;
assertTrue(result == 5.0);
}
- 运行测试用例,这里有2种方法可以使用:
- 静态类型:覆盖runTes()和定义测试函数。最常用的就是采用java的匿名类,如下:
TestCase test= new MathTest(“add”){
public void runTest() { testAdd();}
};
test.run();
- 动态类型:使用反射来实现runTest,它动态地发现并调用的方法,在这种情况下,测试案例的名字对应的测试方法来运行,如下:TestCase=new MathTest(“testAdd”);
test.run();
相比之下,第2种更符合面向对象的思维。
第二步:将TestCase添加到TestSuilt
1
2
3 1 TestSuite suite= new TestSuite();
2
3
1
2
3 1 suite.addTest(new MathTest("testAdd"));
2
3
由于TestSuite可以自动从TestCase中提取测试单元并运行,也可以用如下方法:
1
2
3 1 TestSuite suite= new TestSuite(MathTest.class);
2
3
一个测试用例就完成了,想要更加详细的了解junit.framework,还是到Android SDK中仔细阅读。
前面我们学习了junit.framework包,本篇幅我们开始学习android.test包,了解AndroidSDK是如何扩展junit.framework包。
首先整理android.test包的结构,如下图所示:
在前面的篇幅中说明过:TestCase与TestSuite之间的关系,有些类似于图元对象与容器对象之间的关系。有了这个思想,顺着这张的主线图从上往下看:首先看到的是TestCase类,接着看到InstrumentationTestCase、AndroidTestCase,最后看到ApplicationTestCase,ProviderTestCase2,ServiceTestCase,ActivityTestCase。这不就是Android系统中4大组成元素:Activity、Provider、Service、BroadCast中的前3个,然后我们在看下AndroidSDK中的说明:
类 | 说明 |
AndroidTestCase | 如果你要访问资源或其他东西依赖于Activity的环境,在这个类的基础上扩展。 |
ActivityInstrumentationTestCase2 <T extends Activity> | 这个类提供了一个单一的活动功能测试 |
ApplicationTestCase <T extends Application> | 提供了一个框架,可以在受控环境中测试Application类 |
ProviderTestCase2 <T extends ContentProvider> | 提供了一个框架,可以在受控环境中测试ContentProvider类 |
ServiceTestCase <T extends Service> | 提供了一个框架,可以在受控环境中测试ServiceTest类。 |
1 | 1 |
这些类就不在这里说明,应该与我们平时使用Activity、Service、Provider基本一样。下面举个例子,来说明如何使用这些类,我们就将上一篇J2SE测试例子,在Android中实现:
//MathTest.java
import android.test.AndroidTestCase;
import android.util.Log;
public class MathTestextends AndroidTestCase
{
protected double fValue1;
protected double fValue2;
protected double fRe;
static final StringLOG_TAG = “MathTest”;
protected void setUp() {
fValue1= 2.0;
fValue2= 3.0;
fRe = 5.0;
}
public void testAdd()
{
Log.d( LOG_TAG, “testAdd” );
assertTrue( LOG_TAG+”1″, ( (fValue1 + fValue2 )== fRe ) );
}
}
//ExampleSuite.java
import junit.framework.TestSuite;
public class ExampleSuiteextends TestSuite
{
public ExampleSuite()
{
addTestSuite( MathTest.class );
}
}
与上一篇的例子比较后发现,除了引用的包、父类不一样以外,其他部分是完全一样的,在AndroidAVD上运行程序后看到的结果如下:
单击按钮“Launchtest”运行测试用例,输出测试结果,我们的测试都通过了。这个测试界面是我们自己编写的单元测试的界面,下一篇幅我们将重点介绍这部分。
总结说明
这里我们简要学习了android.test包,其实这个的内容远不止这些,包含:3个Interface、20个class、2个Error,列举如下:
android.test包深入的学习,只有到AndroidSDK中去仔细阅读了。通过学习android.test,让我们对Android系统的组成元素:Activity、Provider、Service有了更加深入的了解