本文共 6444 字,大约阅读时间需要 21 分钟。
本节书摘来自异步社区《Android 应用测试指南》一书中的第1章,第1.4节测试的种类,作者 【阿根廷】Diego Torres Milano(迭戈 D.),更多章节内容可以访问云栖社区“异步社区”公众号查看
1.4 测试的种类
在开发过程中,任何时间段都可以参与测试,这取决于采用何种测试方案。但是,我们推荐测试工作在项目开发早期就介入,甚至可以在完整需求出来之后、刚开始开发的时候就开始做准备。基于被测对象的不同,有好几种不同的测试方法。但是无论采用哪种测试方法,测试用例都包含执行条件和执行结果,执行结果返回True或者False来表示用例是否正确。
1.4.1 单元测试
单元测试,指的是程序员在开发阶段写的测试用例。这种测试用例需要将被测对象独立隔离起来,也就是Mock掉外部关联对象。单元测试用例应用是可以重复执行的。这也是为什么我们常把单元测试和Mock对象关联在一起。因为你要通过Mock对象来模拟外部交互从而达到隔离被测对象的目的。当然,这样的用例可以重复执行任何次数。例如,假设你要从数据库中删除某些数据,但是下一次执行这个用例时这些数据还需要用,因此,不希望这些数据真正被删除,这时候Mock数据库的返回,假装数据已经删除成功了。JUnit是约定俗成的标准单元测试框架。它是一个简单、开源的自动化单元测试框架,由ErichGamma和KentBeck两位作者创建。
Android要用JUnit 3。这个版本没有注释,而是通过内部自查来感知测试用例的。一个典型的JUnit测试用例写法如框1.1中所示的代码,其中测试方法用高亮度显示。
框1.1 JUnit测试代码样例
/*** Android Application Testing Guide*/package com.example.aatg.test;import JUnit.framework.TestCase;/*** @author diego*/public class MyUnitTests extends TestCase { private int mFixture; /*** @param name test name*/ public MyUnitTests(String name) { super(name); } /* (non-Javadoc)* @see JUnit.framework.TestCase#setUp()*/ protected void setUp() throws Exception { super.setUp(); mFixture = 1234; } /* (non-Javadoc)* @see JUnit.framework.TestCase#tearDown()*/ protected void tearDown() throws Exception { super.tearDown(); } /*** Preconditions*/ public void testPreconditions() { } /*** Test method*/ public void testSomething() { fail("Not implemented yet"); }}
如果你是从其他地方购买的书,可以访问来注册用户,然后我们将源代码文件直接发E-mail给您。
我们将在下一节详细阐述测试用例的每个细节。1.测试套件
测试套件是个为人熟知的名词,它表示执行用例的标准流程模式。每个测试用例都用同一套标准流程。因此,它也是测试用例设计的基础。通常情况下,按照Android的约定,它由一系列成员变量构成。通常以m开头,如: mActivity。但是,它也有一些扩展数据,作为数据库和文件系统操作的特殊入口。
2.setUp方法
这个方法是用来初始化测试套件用的。通过重载这个方法,你可以新建对象,初始化元素。在每个测试用例执行之前,这个SetUp方法都会执行一次。
3.tearDown方法
tearDown方法是在测试套件中最后执行的函数。在测试用例执行过程中,会初始化一些对象,这些对象可以在tearDown函数中进行销毁。因为tearDown函数是每个测试用例最后必须执行的,是销毁对象的最佳阶段。
比如:你可以在tearDown中释放掉数据库连接以及网络连接。
JUnit设计的流程是这样的:首先,将整个库的用例都编译完;然后,在第二阶段再执行测试用例。因此,在测试执行过程中,执行器对所有用例都有强依赖。也就是说,对于那些用例很多、耗时很长的用例来说,在所有用例完成之前,是不会对变量、对象进行回收的。这点在Android测试中特别重要,因为在某些设备上测试失败的原因不是因为固有的逻辑问题,而是因为用例执行太多导致资源不足了。
因此,在Android应用中,你若测试使用了额外的、有限的资源,比如Services服务或者ContentProvides,那么,你应该注意要及时释放掉。在tearDown方法中,严格遵守将对象设置成null的规则,以便及时回收,避免一直占用资源,一直到所有用例运行完才释放。
4.测试前期条件
通常,前置条件没法按照正常流程来测,因为常规的测试用例次序是随机的。因此,通常会写一个testPrecondition用例来专门测前置条件。虽然没法保证测试用例以一个特别指定的顺序进行,但是,将所有测前置条件的用例放在指定的地方是一个好的习惯,可以提高用例的可读性。5.实际测试
所有公有类型、返回值为void并且以test开头的函数都会被当作测试用例。JUnit 3不采用标注来标识测试用例,而采用函数名,这点与JUnit 4相反。在Android测试框架中,标注有@SmallTest、@MediumTest、@LargeTest,但是这些注释不会将一个函数标识为测试函数,他们是将测试用例分组的注释。通过分组,你可以选择性地执行某个组下面的所有用例。实际测试的第一条规则,用描述性名字来命名测试用例,或者以测试条件命名。
比如testValues()、testConversionError()、testConversionToString(),这种命名方式是靠谱的。
测试时,要注意不仅仅是走正常的用例,异常和错误的测试用例也要覆盖到。在特定条件下执行用例后,要注意检查周边影响以及函数返回值是否跟预期一致。JUnit提供了一系列的断言assert*函数,它们将预期和真实结果作对比,不一致的时候抛出异常。这样,测试执行器将会处理这些异常,并在最终的结果中展现出来。
断言方法有很多,可以接受不同类型的参数,包括:
assertEquals();assertFalse();asssertNotNull();assertNotSame();assertNull();assertSame();assertTrue();fail()。
除了Junit提供的以上断言方法,Andriod扩展了两个特别的断言类:
MoreAsserts;ViewAsserts。
6.Mock对象
Mock对象是指不调用真实的对象,而是调用模拟对象,获得指定结果,以达到将测试单元隔离的目的。通常,使用这种方法是为了保证被测对象能够正常调用,并且,就像上面提到的,将被测对象跟周边环境隔离开。这样一来,测试用例就可以不受外部影响了,可以独立执行,并且可以重复执行。
Android测试框架支持Mock多个对象,这点对编写测试用例十分有用。当然,这些编译测试用例需要依赖一些东西。
Andriod测试框架提供的几个Mock类如下:
MockApplication;MockContentProvider;MockContentResolver;MockContext;MockCursor;MockDialogInterface;MockPackageManager;MockResources。
几乎平台上所有与你交互的部件都可以由以上几个类来生成。但是,它们并非真正执行,而是在每个方法产生UnsupportedOperationException的地方打桩,这样一来,你就可以创建你真正的Mock的对象,实现Mock的内容了。
7.UI测试
最后,你在测UI部件的时候,需要考虑一些特殊因素。众所周知,在Android应用中只有主线程才允许更改界面交互。只有带有@UIThreadTest标记的函数才会在主线程执行,因此用来测界面的用例需要这个标记。另一方面,如果你想在UI线程中执行一部分测试用例,可以使用Activity.runOnUiThread方法,这个方法提供了可执行的测试操作。TouchUtils是一个帮助类,提供了UI测试的常用帮助,指引你调用一般的事件方法,将事件传递到界面上,比如:
Click点击;
drag拖曳;long click长点击;scroll滚动;tap拍;ouch触摸。通过上述方法,你可以在测试用例中真实地远程控制您的应用程序。8.Eclipse和其他IDE支持
Eclipse完全支持JUnit,而AndroidADT插件方便你测试Android工程。更有甚者,你无需使用IDE也可以执行测试用例和分析测试结果。Eclipse也有个优势:在Eclipse里执行测试用例,执行不正确的时候,可以通过debug的方式,同时调试用例和代码。
在图1.2所示中,我们可以看到Eclipse执行了18个测试用例,花了20.008秒的时间,没发现问题,0失败。测试用例的名称以及执行过程都有展示。如果有一个失败了,错误跟踪会显示相关的信息。
图1.2 JUnit执行结果在Eclipse中的展示
其他IDE,像ItelliJ和Netbeans虽然集成Android开发的插件,但是并没有官方支持。
如果你现在没有在IDE中开发,你可以用ant来执行测试用例(如果你不熟悉这个ant工具请访问)。通过Android命令行,用create test-project命令来启动,这个命令的帮助文字如框1.2所示。
框1.2 命令帮助信息
$ android --help create test-projectUsage:android [global options] create test-project [action options]Global options:-v --verbose Verbose mode: errors, warnings and informational messagesare printed.-h --help Help on a specific command.-s --silent Silent mode: only errors are printed out.Action "create test-project":Creates a new Android project for a test package.Options:-p --path The new project's directory [required]-m --main Path to directory of the app under test, relative to thetest project directory [required]-n --name Project name
1.4.2 集成测试
集成测试目的是用来测试模块与模块之间的交互情况。一般情况下,模块先会经过独立的单元测试,然后再组装在一起集成测试。通常,Android应用上的活动需要跟操作系统进行交互。它们通过ActivityManager来控制活动的生命周期,访问资源、文件系统和数据库。
其他组件,譬如Services(服务组件)和ContentProviders(共享数据)也是同样的原理。它们也需要跟系统的其他部分进行交互来完成相应的功能。
在所有的测试用例中,Android测试框架提供了特殊的测试用例,以便测试上述组件。
1.4.3 功能或者验收测试
在敏捷开发项目中,功能测试或者说验收测试一般是由业务方和测试人员来编写。这些用例通常是以业务场景的表达方式来给大家展现的。这里会有高层次的测试用例,用来测试一个用户需求或者特性的正确性和完整性。虽然这些测试用例是由客户、业务分析员、测试人员和开发人员协商制定的理想结果,但客户(产品的拥有者)是这些测试用例的首要负责人。在这方面,有一些框架和工具可以帮助你,最著名的FitNesse,如图1.3所示,一句话,他们让你在Android开发阶段,轻松集成测试。另外还可以创建测试用例并且验证结果。
图1.3 FitNess集成测试结果图
最近,“行为驱动开发”BDD的新型模式风靡起来,简单说来,可以理解成“测试驱动开发”TDD的革新。“行为驱动开发”的目的在于在业务和技术人员之间建立起统一的术语以便增加相互之间的沟通理解。
“行为驱动开发”可以理解为基于活动的框架,有以下3个原则:
业务与技术要以相同的方式来描述系统;
任何系统都要有确认的、可以衡量的业务价值;从最开始的分析、设计以及计划,都需要有明确的产出。有了以上几个原则,业务人员通常都会参与测试用例的场景设计,并站在业务的角度,利用一些工具实现,比如jbehave。在下面的例子中,测试用例用类似于编程语言的方式表达出场景。测试用例场景描述
我们举个非常简单的例子来描述将场景转换成代码的方法。场景如框1.3中所述。
框1.3 场景描述
假设我有一个温度转换器,当我输入100摄氏度时,我得到的结果是212华氏温度。这个场景翻译成代码如框1.4中所示。框1.4 对应框1.3翻译出来的伪代码
@Given(“我有一个温度转换器”)public void createTemperatureConverter(){ // do nothing} @When(“我将摄氏温度输入对应的文本框”)public void setCelsius(int celsius){ mCelsius=Celsius;} @Then(“我将在华氏温度的字段看到相应的华氏温度”)public void testCelsiusToFahrenheir(int fahrenheit){ assertEquals(Fahrenheit, TemperatureConverter.celsiusToFahrenheit (mCelsius));}
1.4.4 性能测试
性能测试,是用重复的方式来探测部件中某些特点的性能。如果说,应用的某些地方对性能提升有要求,那么最好的衡量优化效果的办法,就是拿优化之前和优化之后给出的性能报告做对比。众所周知,一次考虑不周到的优化带来的后果总是弊大于利的,因此,为了避免优化后不仅没达到效果,反而把之前的功能影响到了,最好对应用的整体性能有个清晰的了解,明确升级之后对应用的影响。
Android 2.2里面的Dalvik JIT编译器改变了一些Android开发中常使用的优化方案。迄今,在Android开发中,每一个性能优化升级都推荐有性能测试保证。
1.4.5 系统测试
系统测试是将部件组合起来作为一个整体来测试,检查部件之间的交互情况,软件和硬件都会涉及。通常,系统测试包括以下额外的测试类,比如:界面GUI测试;
冒烟测试;性能测试;安装测试。转载地址:http://vxvfl.baihongyu.com/