1.3 为什么要测试、测什么、如何测、何时测试
大家都清楚早期发现Bug会节约一大笔项目资源、减少软件维护费用。这就是为开发项目写测试用例的最好理由,不久你就会发现效率提高了。
另外,写测试用例的过程中,迫使你对需求了解更透彻,对要解决的问题了解更深入全面。如果你不了解被测对象,是不可能写好测试用例的。同样,写好测试用例可以清晰了解旧程序和第三方代码,让你能力倍增,更加有信心升级(旧程序、第三方代码)代码。
测试覆盖率越高,发现隐藏Bug的概率就越高。通过覆盖率分析,发现测试用例没有覆盖到的地方,就应该新增测试用例。
测试覆盖技术需要Android平台构造一个特殊的监控器来收集监测数据,但是不能发布,因为它会影响性能,从而严重影响应用的表现。
为了弥补这个空白,请访问EMMA。它是一个开源工具,用于测量和报告Java代码测试覆盖率,可以衡量类的覆盖率。它的报告有几个维度:
类覆盖率;
方法覆盖率;
行覆盖率;
基础块覆盖率。
覆盖率报告同样可以设置成不同的格式。从某种程度上说,EMMA是基于Andoid框架的,所以,可以建一个带EMMA模拟器版本的Android系统。
我们将在第10章分析EMMA在Android系统上的用法,带大家完成一次完整的覆盖率测试,采用非传统的测试策略。
图1.1展示了在装了兼容的plugin后,经过EMMA覆盖率分析后,用Eclipse编辑器打开并分析的文件,绿色(运行后可看到,全书同)的代码行表示该行已经覆盖到了。
图1.1 EMMA覆盖率分析结果
不幸的是,这个插件不支持Android测试,因此,你只能用它来做Junit单元测试,而且你只能通过HTML来看Android覆盖率分析报告。
测试应该有自动化,每当你更改或者新增代码时,你就可以运行一部分或者全量测试用例来确保之前的逻辑是对的,以及新代码逻辑也是符合测试预期的。这就是我们说的持续集成,第8章我们将介绍。它依赖于自动化测试和自动化构建过程。
如果你没用到自动化测试,那实际上不可能把持续集成作为开发过程的一部分,而且很难保证代码变更情况下,不破坏现有代码逻辑。
1.3.1 测试的内容是什么呢
一个Android应用,测试点是什么呢?严格地说,代码的每一行都应该经过测试。不过,根据不同的测试标准,你可以采用只需要覆盖到重要的路径分支或者一部分重要内容的方法。通常,有一些不可能被打破而产生Bug的地方就没有必要测试。比如:getter方法和setter方法测起来就没啥意思。这就好比编译器早就有自己的测试工程,而你也不可能在自己的代码中来测试编译器一样。
除了程序功能属于测试要点之外,Android应用还有一些特殊的地方需要考虑。我们将在下面几节进行描述。
1.3.2 Activity生命周期中的事件
Activity对生命周期中的事件是否能够正确响应是一个测试点。
比如,你的Activity在OnPause()事件和OnDestroy()事件中需要保存自身的状态,然后在OnCreate(Bandle savedInstanceState)时恢复状态。那么,你应该重复执行并验证在这些条件下状态是否能够正确保存、是否能恢复正常。
在测Activity时,还需要验证配置项变化事件的响应。因为配置变化后,当前的Activity需要重新生成。此时,你要验证新生成的Activity对事件的响应是否正常以及先前的状态是否恢复正常。定时循环事件也会触发配置的变化。因此,你还要看看应用是否能够正确处理这些事件。
1.3.3 数据库和文件系统的操作
数据库操作和文件的正确读写也是一个测试点。对这些操作的测试应该在底层系统测试中完成,在ContentProviders中进行高层次的测试,需要跟应用本身隔离开。
要对这些部件进行独立的测试,Android提供了Mock对象的工具,在andriod.test.mock包中。
1.3.4 设备的物理特征
在你发布应用程序之前,要确保它能在不同的设备上正常运行。至少你能把握大概的情况并想好对策。
在设备的物理特性中,有以下几个测试点:
网络容量;
屏幕分辨率;
屏幕厚度;
屏幕尺寸;
传感器;
键盘和其他输入设备;
GPS;
扩容。
由于有上述几个方面需要测试,虚拟器尤为重要。因为虚拟器可以让你通过简单配置达到上述条件的硬件特性。但是,如之前提到的,到最后的测试阶段,还是要用真机来操作,模拟真实用户的使用过程来测试。