《Android 应用测试指南》——第1章,第1.4节测试的种类

简介:

本节书摘来自异步社区《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");
   }
}

如果你是从其他地方购买的书,可以访问http://www.PacktPub.com/support来注册用户,然后我们将源代码文件直接发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失败。测试用例的名称以及执行过程都有展示。如果有一个失败了,错误跟踪会显示相关的信息。


7603642d71b4cd678a27844a9665cc039b5fafa4

图1.2 JUnit执行结果在Eclipse中的展示

其他IDE,像ItelliJ和Netbeans虽然集成Android开发的插件,但是并没有官方支持。

如果你现在没有在IDE中开发,你可以用ant来执行测试用例(如果你不熟悉这个ant工具请访问http://ant.apache.org)。通过Android命令行,用create test-project命令来启动,这个命令的帮助文字如框1.2所示。

框1.2 命令帮助信息

$ android --help create test-project
Usage:
android [global options] create test-project [action options]
Global options:
-v --verbose Verbose mode: errors, warnings and informational messages
are 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 the
test project directory [required]
-n --name Project name

1.4.2 集成测试
集成测试目的是用来测试模块与模块之间的交互情况。一般情况下,模块先会经过独立的单元测试,然后再组装在一起集成测试。

通常,Android应用上的活动需要跟操作系统进行交互。它们通过ActivityManager来控制活动的生命周期,访问资源、文件系统和数据库。

其他组件,譬如Services(服务组件)和ContentProviders(共享数据)也是同样的原理。它们也需要跟系统的其他部分进行交互来完成相应的功能。

在所有的测试用例中,Android测试框架提供了特殊的测试用例,以便测试上述组件。

1.4.3 功能或者验收测试
在敏捷开发项目中,功能测试或者说验收测试一般是由业务方和测试人员来编写。这些用例通常是以业务场景的表达方式来给大家展现的。这里会有高层次的测试用例,用来测试一个用户需求或者特性的正确性和完整性。虽然这些测试用例是由客户、业务分析员、测试人员和开发人员协商制定的理想结果,但客户(产品的拥有者)是这些测试用例的首要负责人。

在这方面,有一些框架和工具可以帮助你,最著名的FitNesse,如图1.3所示,一句话,他们让你在Android开发阶段,轻松集成测试。另外还可以创建测试用例并且验证结果。


344dbe706e207dda6b7842442fc688d7df1dc0a7

图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测试;
冒烟测试;
性能测试;
安装测试。

相关实践学习
通过性能测试PTS对云服务器ECS进行规格选择与性能压测
本文为您介绍如何利用性能测试PTS对云服务器ECS进行规格选择与性能压测。
相关文章
|
1天前
|
缓存 移动开发 Android开发
构建高效Android应用:从内存优化到电池寿命
【5月更文挑战第18天】在移动开发领域,一个优秀的Android应用不仅要拥有流畅的用户界面和丰富的功能,更要在设备资源有限的前提下保持高效运行。本文将探讨Android应用开发中关键的性能优化策略,包括内存使用优化、CPU使用减少和电池寿命延长等方面。通过分析常见的性能瓶颈和提供实用的解决方案,帮助开发者打造更高效、更受欢迎的Android应用。
|
1天前
|
移动开发 Android开发 UED
构建高效Android应用:探究Kotlin协程的优势与实践
【5月更文挑战第17天】 在移动开发领域,尤其是针对Android平台,性能优化和流畅的用户体验始终是开发者追求的目标。Kotlin作为一种现代的编程语言,自引入Android开发以来,其简洁、安全和互操作性的特点受到广泛欢迎。特别是Kotlin协程的推出,为解决Android平台上的并发编程问题提供了新的思路。本文将深入探讨Kotlin协程的核心优势,并通过实例展示如何在Android应用中有效利用协程来提高响应性和稳定性,从而改善整体的用户体验。
|
2天前
|
移动开发 API Android开发
构建高效Android应用:探究Kotlin协程的优势与实践
【5月更文挑战第17天】在移动开发领域,性能优化和流畅的用户体验一直是开发者追求的目标。针对Android平台,Kotlin语言凭借其简洁性和功能丰富性成为了许多开发者的首选。其中,Kotlin协程作为异步编程的强大工具,为处理并发任务提供了轻量级的解决方案。本文深入探讨了Kotlin协程的核心优势,并通过实例分析其在Android开发中的应用,旨在帮助开发者提升应用的性能和响应能力。
|
2天前
|
Android开发
Android Jetpack架构开发组件化应用实战,字节跳动+阿里+华为+腾讯等大厂Android面试题
Android Jetpack架构开发组件化应用实战,字节跳动+阿里+华为+腾讯等大厂Android面试题
|
2天前
|
数据库 Android开发 开发者
打造高效Android应用:Kotlin协程的全面应用
【5月更文挑战第17天】随着移动开发技术的不断进步,开发者寻求更高效的编程模式来提升应用性能和用户体验。本文深入探讨了Kotlin协程在Android开发中的应用,揭示了如何利用这一现代并发解决方案来简化异步编程,提升应用响应速度,并确保用户界面的流畅性。通过实例分析,我们将展示Kotlin协程如何与Android框架无缝集成,以及它们在处理网络请求、数据库操作和耗时任务时的优势。
8 1
|
2天前
|
移动开发 Android开发 开发者
构建高效Android应用:探究Kotlin协程的优势与实践
【5月更文挑战第17天】 在移动开发领域,尤其是针对Android平台,性能优化和流畅的用户体验始终是开发者追求的目标。近年来,Kotlin语言因其简洁性和功能性而成为Android开发的热门选择。其中,Kotlin协程作为一种轻量级的线程管理方案,为编写异步代码提供了强大支持,使得处理并发任务更加高效和容易。本文将深入探讨Kotlin协程的核心优势,并通过具体实例展示如何在Android应用中有效利用协程来提升性能和用户体验。
|
2天前
|
敏捷开发 Java Devops
深入理解与应用软件测试中的Mock技术
【5月更文挑战第17天】 在现代软件开发过程中,单元测试是保证代码质量的重要手段。然而,对于依赖外部系统或服务的功能,如何有效进行单元测试一直是一大挑战。Mock技术的引入为这一难题提供了解决方案。本文将详细探讨Mock技术的概念、应用场景以及在实际软件测试中的优势和局限性,同时提供一些最佳实践和常见框架的使用指南。
|
2天前
|
移动开发 Android开发 UED
构建高效Android应用:探究Kotlin协程的优势与实践
【5月更文挑战第17天】 在移动开发领域,性能优化和流畅的用户体验始终是核心追求。针对Android平台,Kotlin协程作为一种新兴的轻量级线程管理方案,正逐渐改变开发者对于异步编程和后台任务处理的认识。本文通过深入分析Kotlin协程的原理、优势以及在实际Android应用中的使用案例,揭示了如何利用协程提高应用性能,减少资源消耗,并最终实现更流畅的用户体验。我们将通过一系列实验证据,展示协程如何在不牺牲可读性和可维护性的前提下,提升代码执行效率,并为Android开发社区提供一种新的并发处理范式。
|
2天前
|
Java 测试技术 数据库
深入理解与应用软件测试中的Mock对象
【5月更文挑战第17天】在软件开发过程中,单元测试是确保代码质量的重要环节。本文将深入探讨Mock对象在软件测试中的应用,分析其对提升测试效率和准确性的重要性。通过具体案例,我们将了解如何创建和使用Mock对象,以及它们如何帮助开发者隔离依赖,模拟外部系统行为,从而使得单元测试更加高效和可靠。
|
2天前
|
移动开发 调度 Android开发
构建高效Android应用:Kotlin协程的全面应用
【5月更文挑战第17天】随着移动开发技术的不断进步,开发者寻求更高效、响应更快的应用程序。在Android平台上,Kotlin作为一种现代编程语言,提供了协程这一强大的并发处理工具。本文深入探讨了如何在Android应用中使用Kotlin协程来提升性能和用户体验,同时保证代码的简洁性和可维护性。我们将分析协程的核心概念,并通过实例展示其在实际开发中的应用。

热门文章

最新文章