标签:
android测试框架(Android Testing Framework)是开发环境的一部分,它提供了架构和强大的工具帮助你从单元到框架测试应用的各个方面。
关键特性:
本文档描述了android测试框架的基础,包含测试结构、开发测试的API以及启动测试和查看测试结果的工具。本文假设你有android应用编程以及JUnit测试的基础。
测试框架图如下:
android的构建和测试工具假设测试项目都组织成类似测试、测试类、测试包和测试项目的标准结构。
android测试基于JUnit。通常JUnit测试就是测试“待测试应用”的方法。测试方法构成的类为test cases (或者test suites)。
JUnit
中编译测试源文件到class文件中。类似地android中用android的编译工具编译测试包中的测试源文件为class文件。在JUnit
中test runner来执行测试类。在android中使用测试工具加载测试包和被测应用,然后调用android的test runner。
测试项目就是一个目录或者eclipse 工程,可在其中新建源代码、manifest文件以及测试包的其它文件。建议使用Android tool创建测试项目:
推荐的目录结构:
MyProject/
AndroidManifest.xml
res/
... (resources for main application)
src/
... (source code for main application) ...
tests/
AndroidManifest.xml
res/
... (resources for tests)
src/
... (source code for tests)
注:这个在实际操作中往往根据IDE而不同,请以具体IDE的实例为准。
Android测试API基于JUnit API 并扩展了instrumentation框架和Android特有的测试类。
使
用JUnit的TestCase类可对未使用android
API的类进行单元测试。TestCase也是AndroidTestCase(测试依赖于android的对象)的基类。
AndroidTestCase还提供了android特有的 setup、teardown以及其它帮助方法。
JUnit的Assert类可以显示结果,assert方法比较期望值与实际结果,在比较失败时抛出异常。android同样提供了扩展了比较类型的断言类,以及用来测试UI的断言类。
注意android测试API支持JUnit 3的代码风格,不支持JUnit 4。
android instrumentation是android系统中一系列控制方法或钩子(hooks)。这些钩子可以的正常生命周期内独立地控制组件。它同样可以控制android如何加载应用。
通
常android组件会按照系统指定的生命周期来运行,例如Activity的生命周期开始于它被Intent激活,其onCreate()方法会被调
用,接下来是onResume(),当用户启动另外一个应用,onPause()方法会调用
,如果Activity调用finish()方法,它的onDestroy()方法也会被调用。android framework
API不会提供方法让你在代码中直接调用这些回调方法,但是用instrumentation可以。
系统把应用中的所有组件运行在同一个进程中,你可以让一些组件,比如content provider,运行在单独的进程中。但是无法强制应用与另外其他正在运行的应用运行在同一个进程中。
通过android imstrumentation,你可以在测试代码中直接调用回调方法,让你渗透组件的生命周期,就像调试。下面的测试代码演示了如何用instrumentation来测试Activity保存和恢复状态:
// Start the main activity of the application under test
mActivity = getActivity();
// Get a handle to the Activity object‘s main UI widget, a Spinner
mSpinner = (Spinner)mActivity.findViewById(com.android.example.spinner.R.id.Spinner01);
// Set the Spinner to a known position
mActivity.setSpinnerPosition(TEST_STATE_DESTROY_POSITION);
// Stop the activity - The onDestroy() method should save the state of the Spinner
mActivity.finish();
// Re-start the Activity - the onResume() method should restore the state of the Spinner
mActivity = getActivity();
// Get the Spinner‘s current position
int currentPosition = mActivity.getSpinnerPosition();
// Assert that the current position is the same as the starting position
assertEquals(TEST_STATE_DESTROY_POSITION, currentPosition);
代码中使用的关键方法是getActivity(),它属于android instrumentation API。调用该方法才会启动Activity。你可以提前配置测试所需的环境(test fixture)。
Instrumentation可以加载测试包和被测试应用到同一个进程,这样测试代码可以调用应用组件的方法,修改和检查组件中的域。
android提供了几个继承自TestCase和Assert的test case 类,它们都有andorid 特有的setup、teardown以及其它的辅助方法。
通用的test case类,继承了TestCase和Assert类。它提供了标准的JUnit中的setup()和teardown()方法,同时还有JUnit的Assert方法。另外它也提供了用来测试权限的方法以及通过清除一定的类引用来防止内存泄露的方法。
android测试框架的一个重要特点是组件test case类。它们有独特的setup和teardown及控制组件生命周期。同时它们也提供mock方法。
1、Activity Testing
2、Content Provider Testing
3、Service Testing
Android并没有为 BroadcastReceiver提供单独的test case 类。可以通过测试发送Intent对象给它的组件来测试BroadcastReceiver,检查BroadcastReceiver回复是否正确。
用
ApplicationTestCase测试Application对象的setup和teardown。这些对象维护着应用程序包中所有组件信息的全局
状态,该test case 用于验证manifest 文件中的<application>元素是否正确配置。然而记住这个test
case无法控制应用包组件的测试。
如果想在test case 类中使用 instrumentation 的方法,必须使用InstrumentationTestCase或者它的子类。Activity test case 继承该基类。
Android test case 类继承自JUnit,可以用断言来显示测试结果。assertion方法将测试返回的真实值和期望值进行比较,如果比较失败它会抛出AssertionException。用Assertion比打印log更方便,有更好的测试性能。
除了JUnit的Assert类的方法,测试API同时也提供了MoreAsserts和ViewAsserts类:
为了解决测试过程中的依赖,Android提供了创建模拟系统对象的类,比如Context对象、
ContentProvider对象、ContentResolver对象以及Service对象。有些test
case能模拟的Intent对象。通过使用这些模拟对象,你可以将测试与系统的其余部分隔离开,同时也满足了测试中的依赖,这些类都在包
android.test和android.test.mock中。
模拟对象通过打桩或者重载正常操作来实现将测试与正在运行的系统隔
离。例如MockContentResolver对象用它自有的与系统隔离的本地框架来代替通常的resolver框架。同时
MockContentResolver不使用notifyChange(Uri, ContentObserver,
boolean)方法,这样测试环境以外的observer对象不会被意外触发。
模拟对象类也通过提供正常类的子类来满足测试的依赖,该子类除了你覆写的方法外其它都是不起作用的。例如,MockResources对象是Resources类的子类,每个方法在调用时都会抛出异常。要使用它,你只需要重载需要的方法。
下面是Android中可用的模拟对象类:
MockApplication、
MockContext、MockContentProvider、MockCursor,、MockDialogInterface、
MockPackageManager和MockResources提供了简单有用的模拟策略(打桩),在调用时都会抛出
UnsupportedOperationException异常。使用它,你只需要重载需要的方法。
注意:MockContentProvider和MockCursor是API Level 8 中新加入。
MockContentResolver
通过屏蔽系统正常的resolver框架来为content provider
提供隔离的测试。MockContentResolver不是在系统中查找提供authority的content
provider,而是使用自己的内部表,你必须显式地用addProvider(String,
ContentProvider)方法将provider添加到表中。
通过这个特性可以将模拟的content
provider与authority关联,新建provider对象但使用测试数据,你甚至可以设置provider的authority为null。
实际上MockContentResolver对象将你的测试与包含真实数据的provider隔离。你可以控制provider的功能并防止测试影响真
实数据。
android提供了两个Context类来提供测试:
test case由test runner类运行,test runner加载test
case类、初始化、运行及清理测试。android test runner必须配置,这样启动应用的系统工具可以控制测试包如何加载test
case和被测试应用。一般在manifest文件中设定。
InstrumentationTestRunner是android中主要的test runner类,它扩展了JUnit test runner框架并且是已配置,能够执行任何android系统提供的test case 类并且支持所有类型的测试。
你
可指定测试包的manifest文件的<instrumentation>标签内容为Instrumentation
或其子类。InstrumentationTestRunner的代码在共享库android.test.runner中,所以它通常没有链接到你的代
码,必须在<uses-library>标签中指定。通常不需要手动去设定,Eclipse ADT以及android
命令行工具都会自动生成它们并且把它们加到测试包的manifest文件中。
注意:如果使用的是InstrumentationTestRunner之外的test runner,必须修改<instrumentation>标签并指向你想使用的类。
要运行InstrumentationTestRunner类必须用android 工具调用内部系统类。Eclipse ADT中这些类都会被自动调用,命令行工具执行测试的时用Android Debug Bridge (adb)运行这些类。
系
统类加载和启动测试包,杀掉被测试应用包正在运行的进程,并且重新加载被测试包的实体,然后它们把控制权交给
InstrumentationTestRunner,由它来执行测试包中的每个test case。你也可以通过Eclipse
ADT中的setting或者命令行工具中的flag来控制哪些 test case或者方法的运行。
既不是系统类也不是
InstrumentationTestRunner运行被测试应用,而是test
case。它要么调用被测试包中的方法,要么调用它自己的方法以改变被测试包生命周期。应用程序完全由test case 控制,测试开始前由test
case来初始化测试环境,
关于更多的运行测试,可以参见 Testing from Eclipse with ADT和 Testing from Other IDEs。
Android
测试框架返回测试结果给启动测试的工具。在eclipse
ADT中结果会在新的JUnit视图面板中显示,命令行会在STDOUT中显示。两者都可以看到显示每个test case
名字和你所运行的方法的小结,同时会看到所有失败的断言,其中包含指向产生失败的测试代码所在行的链接。失败的断言同时也会列出期望值和实际值。
测试结果根据IDE不同而有不同。
SDK提供了两个应用测试工具:
测试环境需要同时处理android应用包名和java包标识符。它们都使用同样的命名格式,但是代表着完全不同的实体。
android
包名是.apk文件对应的一个独一无二的系统名字,由应用包的manifest文件中<manifest>标签中
的"android:package"属性来设定。测试包的名字必须和被测试包的名字不同,通常android工具会用被测试包的名字后加
上".test"来作为测试包的名字。
测试包也会用包名来定位它所测试的应用,元由测试包的manifest文件中<instrumentation>素的"android:targetPackage"属性设定。
java包标识符对应源文件,包名反映了源文件所在目录,它同时会影响类与成员间彼此的可访问性。
android 工具会帮助你设定测试包的名字。根据你的输入,工具会设定测试包的名字以及测试的目标包的名字。只有在被测试应用工程已经存在的情况下这些工具才会起作用。
默
认情况下,这些工具会将测试类的包标识符设定为与被测试应用的包标示符一致。如果你想暴露被测试包中的一些成员你可能需要做一些修改。如果要修改,只修改
java 包标示符,不要修改android 包名,只修改test case
的源文件而不要修改测试包中R.java文件的包名,因为修改它会造成与被测试包中的R.java类冲突。不要将测试包的android包名修改成和它所
测试的应用的包名一样,因为这样它们的名字在系统中不再是独一无二的。
测试内容
What To Test详细地描述了android应用中应该被测试的关键功能以及可能会影响该功能的状况。
大部分的单元测试是专门针对你正在测试的andorid组件。Activity Testing、 Content Provider Testing和 Service Testing中都有一章节列出“需要测试什么”。
尽量在真实的设备上运行这些测试。其次用Android Emulator来加载已经配置好你所希望测试的硬件、屏幕、版本的android vitual device。
http://developer.android.com/intl/zh-cn/tools/testing/testing_android.html
http://www.uml.org.cn/mobiledev/201306074.asp
本文地址:http://www.cnblogs.com/pythontesting/p/4916574.html
标签:
原文地址:http://www.cnblogs.com/pythontesting/p/4930014.html