版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、Android 上的单元测试【IT168 技术文档】任何程序的开发都离不开单元测试来保证其健壮和稳定。Android 的程序自然也不例外。从 Android SDK 0.9 开始,就有了比较成熟的测试框架,但是直到目前最新的 1.1 版本,也没有详细的文档介绍这个内容,只是简单的给了一个 Api Demos 里的几个单元测试代码。因此,我在这里对此内容做一下梳理和总结:JUnit 还能用么?在 Java 下做单元测试必然用到 JUnit。这里说的 JUnit 是指从 Apache 基金会下载的junit.jar 里提供的一系列单元测试功能。这些功能显然是运行在 JDK 之上的。在 Androi
2、d 下已经没有了 JDK,自然也无法运行 JUnit。但是这并不妨碍我们利用 JUnit 编写单元测试。只不过在运行单元测试时,一定要用 JDK 来运行,利用 java 命令来启动 JUnit 的某个Runner。如果是用 Eclipse 的话,可以在 Run Configuration 里新建一个 JUnit。但是一定要记得在 Classpath 选项卡里将 Bootstrap Entries 中的 Android Library 改成 JRE, 并且添加 junit.jar。很明显的,这种测试就是正规的 Java 单元测试,和 Android 没有任何关系。你无法测试任何关于 Androi
3、d 系统中的 API,你写的 Activity,人机界面等等。所以,如果你想测试仅仅是一些封装数据的对象,或者是纯粹的数值计算,还是可以用这种方法的。Android 里面的 junit.framework 包是怎么回事?很多人看到这个包的时候,第一反应是 Android 是不是已经完整集成了 JUnit。很遗憾这不是事实。如果你按照 JUnit 的运行方法,却不像上面那样改用 JDK,就一定会得到一个异常:# An unexpected error has been detected by Java Runtime Environment: # Internal Error (classFil
4、eParser.cpp:2924), pid=4900, tid=4476 #Error: ShouldNotReachHere()# Java VM: Java HotSpot(TM) Client VM (10.0-b19 mixed mode windows-x86) # An error report file with more information is saved as:# E:MydocEclipseWorkspaceTestAndroidhs_err_pid4900.log # If you would like to submit a bug report, please
5、 visit: #/webapps/bugreport/crash.jsp#实际上,TestCase 这个类用于在 Android 担当所有独特的 TestCase 的基类的作用, 它是一个 Abstract Class。Android 单元测试类继承关系图如下所示:之所以有那么多 XXXTestCase 主要是为了简化工作。例如当你想对一个访问数据库的功能进行测试时,首先需要自己启动并初始化数据库。在这里是类似的,如果你想测试一个 Activity,首先要启动它。而 ActivityTestCase 就会自动帮你做完这些事情。而ActivityUnitTe
6、stCase 会更注重测试的独立性,它会让测试与 Android 底层的联系降到最低。其余的类可以查看相关的 Javadoc 来按需挑选。要编写测试,就是找到合适的XXXTestCase 作为基类来继承,并且编写自己的测试方法。很明显的,最简单的编写测试的方法就是继承 AndroidTestCase 写一个自己的TestCase。然后为自己的一组 TestCase 写一个 Activity 界面,由界面控制 TestCase 的启动,运行和结果报告。但是,你很快会发现,为何要给测试写一个界面呢?这太诡异了。这时就需要一种技术,它可以利用命令行(Shell)来启动一组测试,并且通过命令行的形式给
7、出结果。这就是所谓的 Instrumentation。什么是 Instrumentation?一般在开发 Android 程序的时候,需要写一个 manifest 文件,其结构是:这样,在启动程序的时候就会先启动一个 Application,然后在此 Application 运行过程中根据情况加载相应的 Activity,而 Activity 是需要一个界面的。但是 Instrumentation 并不是这样的。你可以将 Instrumentation 理解为一种没有图形界面的,具有启动能力的,用于监控其他类(用 Target Package 声明)的工具类。任何想成为 Instrumenta
8、tion 的类必须继承android.app.Instrumentation。下面是这个类的解释:“Base class for implementing application instrumentation code. When running with instrumentation turned on, this class will be instantiated for you before any of the application code, allowing you to monitor all of the interaction the system has with
9、the application. An Instrumentation implementation is described to the system through an AndroidManifest.xmls tag.“对于单元测试,我们需要认真了解的就是 android.test.InstrumentationTestRunner 类。这是 Android 单元测试的主入口。它相当于 JUnit 当中 TestRunner 的作用。那么如何加载它呢,首先要在 manifest 文件中加入一行关于 Instrumentation 的声明。比如 Android Api Demos 中的
10、测试里的 manifest 是这么写的(我滤掉了所有的注释):如果用 Eclipse 的 ADT 插件(0.8 版本以上),也可以用图形界面来添加,如下图:编辑好 manifest,就可以打包(build,可以用 Eclipse ADT 来做,也可以用 aapt 命令手工完成),然后安装到虚拟机上(用 adb install 命令)。之后就可以利用命令行的方式来加载你的单元测试了。在 Android Shell 中加载一个 Instrumentation 的方法是利用以下命令:adb shell am instrument w XXXXXX其中-w 是指定 Instrumentation 类的
11、参数标志。一个简单的例子是:adb shell am instrument -w com.android.foo/android.test.InstrumentationTestRunner当然,也可以利用 adb shell 先进入 android 命令行模式,再直接写 am instrument w XXXXXXX。下面将具体介绍如何将根据需要加载一组单元测试。如何在 Android 中利用 Instrumentation 来进行测试?在介绍具体的命令之前,我们先理解一下单元测试的层次。一组单元测试可以被组织成若干个 TestSuite。每个 TestSuite 包含若干 TestCase
12、(某个继承 android.jar 的junit.framework.TestCase 的类)。每个 TestCase 又包含若干个 Test(具体的 test 方法)。如果假设 com.android.foo 是你的测试代码的包的根。当执行以下命令时,会执行所有的 TestCase 的所有 Test。测试的对象就是在 Target Package 中指定的包中的代码:adb shell am instrument -w com.android.foo/android.test.InstrumentationTestRunner如果你想运行一个 TestSuite,首先继承 android.j
13、ar 的 junit.framework.TestSuite 类,实现一个 TestSuite(比如叫 com.android.foo.MyTestSuite),然后执行以下命令执行此 TestSuiteadb shell am instrument -e class com.android.foo.MyTestSuite -w com.android.foo/android.test.InstrumentationTestRunner其中的-e 表示额外的参数,语法为-e arg1 value1 arg2 value2 这里用到了 class参数。如果仅仅想运行一个 TestCase(比如叫
14、 com.android.foo.MyTestCase),则用以下命令: adb shell am instrument -e class com.android.foo.MyTestCase -wcom.android.foo/android.test.InstrumentationTestRunner如果仅仅想运行一个 Test(比如就是上面 MyTestCase 的 testFoo 方法),很类似的,就这样写:adb shell am instrument -e class com.android.foo.MyTestCase#testFoo -w com.android.foo/and
15、roid.test.InstrumentationTestRunner然后,所有的测试结果会输出到控制台,并会做一系列统计,如标记为 E 的是 Error, 标记为 F 的是 Failure,Success 的测试则会标记为一个点。这和 JUnit 的语义一致。如果希望断点调试你的测试,只需要直接在代码上加上断点,然后将运行命令参数的-e 后边附加上 debug true 后运行即可。更加详细的内容可以看 InstrumentationTestRunner 的 Javadoc。我希望 Android 能尽快有正式的文档来介绍这个内容。如何在 Android 的单元测试中做标记?在 androi
16、d.test.annotation 包里定义了几个 annotation,包括LargeTest,MediumTest,SmallTest,Smoke,和Suppress。你可以根据自己的需要用这些 annotation 来对自己的测试分类。在执行单元测试命令时,可以在-e 参数后设置“size large”/ “size medium”/ “size small”来执行具有相应标记的测试。特别的Supperss 可以取消被标记的 Test 的执行。完整的操作过程总结以上所有的内容,编写并运行完整的测试需要以下的步骤:以上步骤中,在 Android 自带的例子中,我发现它有两个 manifes
17、t.xml。也就是说在步骤 3 中源代码和测试代码分别生成了两个不同的包。然后步骤 4 利用 adb install 命令安装到了虚拟机上。由于我没有找到 Eclipse ADT 有办法可以为一个只有 Instrumentation,没有Activity 的 Application 打包并安装,于是采用了略微不同的办法完成了这个工作。下文中将一一详细介绍整个过程。1、编写程序我新建了一个项目 TestApp,参数为: Package Name: com.android.testappActivity Name: MainActivity Application Name: TestApp以下是
18、 MainActivity 的源代码: packagecom.android.testapp; importandroid.app.Activity; importandroid.os.Bundle; publicclassMainActivityextendsActivity /* Called when the activity is first created. */ OverridepublicvoidonCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); setContentView(R.layo
19、ut.main);publicintsum(inta,intb) returna + b;publicintsubstract(inta,intb) returnb - a;其中,我故意将减法的 a b 写成了 b a。2、编写测试程序然后,我新建了一个 Source Folder,名为 test,并在里面新建了包com.android.testapp.test。并定义了一个 TestCase,名为 TestMainActivity,源代码如下:package com.android.testapp.test;import com.android.testapp.MainActivity;im
20、port android.test.ActivityInstrumentationTestCase; import android.test.suitebuilder.annotation.MediumTest;public class TestMainActivity extends ActivityInstrumentationTestCase public TestMainActivity() super(com.android.testapp, MainActivity.class);public TestMainActivity(String pkg, Class activityClass) super(pkg, activityClass);MediumTestpublic void testSum() assertEquals(3, getActivity().sum(1, 2);MediumTestpublic void testSubstract() assertEquals(-1, getActivity().substract(1, 2);我继承了 ActivityInstrumentationTestCase。这个 TestCase 在执行时会自动帮我启动相应的 Activ
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年江西省庐山市高二生物下册期末考试检测卷及完整答案(有一套)
- 2026年贵州省仁怀市高二生物下册期末考试测试卷有完整答案
- 2026年山东省滕州市高二生物下册期末考试考试卷【考点精练】附答案
- 2025年黑龙江省安达市高二生物下册期末考试考试卷(全优)附答案
- 2026年河北省武安市高二生物下册期末考试测试卷及完整答案
- 2026年四川省阆中市高二生物下册期末考试模拟卷含答案(轻巧夺冠)
- 2025年浙江省永康市高二生物下册期末考试模拟卷附答案【黄金题型】
- 2026年江苏省句容市高二生物下册期末考试模拟卷附完整答案(易错题)
- 2026年四川省康定市高二生物下册期末考试试卷附完整答案【典优】
- 2026年山东省莱阳市高二生物下册期末考试模拟卷附参考答案【完整版】
- 2026年安全生产月主题《人人讲安全、个个会应急-排查整治风险隐患》(课件+文字稿)
- 2025年山东青岛市初二学业水平地生会考真题试卷(+答案)
- 2026年秋新教材外研版九年级上册英语Unit 1-8课文+翻译
- 银行从业资格考试题库及答案
- 2025年国家司法考试《商法》试题及答案
- 大班自主游戏观察记录 (49篇)
- 节能新起点低碳向未来宣传
- 国家职业标准 4-10-01-06 家政服务员(整 理收纳师) (2026年版)
- 2026年国家保安员资格考试题库及答案
- 2025年天津市八年级地理生物会考真题试卷+解析及答案
- 2025年甘肃省天水市初二学业水平地生会考真题试卷(+答案)
评论
0/150
提交评论