《精通移动App测试实战:技术、工具和案例》一2.3 应用JUnit对Android项目进行单元测试

2.3 应用JUnit对Android项目进行单元测试

2.3.1 JUnit基于Android项目TestCase的应用

如果我们对基于Android系统项目开发有一定了解的话,相信一定能看出来,其核心代码是计算两个整数相加的函数。我们做单元测试当然也挑选其最核心的函数来进行测试。可以按照如下的步骤来创建一个基于Android项目的测试用例(TestCase)。

第一步:选中“CalculatorOfTwoNum”项目下的“src”目录中的“com.yuy.calculatoroftwonum”包里的“MainActivity.java”文件,单击鼠标右键,从弹出的快捷菜单中选择“New”菜单项,在其弹出的子菜单项中,再选择“JUnit Test Case”选项,如图2-3所示。

在弹出的图2-4所示对话框中,我们选择“New JUnit 4 test”选项。为了便于我们对测试相关的用例进行管理,同时也为了不和原始的项目源代码混在一块,我们将测试用例放到“com.yuy.calculatoroftwonum.test”包下,因为是针对“MainActivity.java”文件进行的用例设计,所以在Name后的文本框输入“MainActivityTest”,该类的父类我们选择“android.test.AndroidTestCase”,创建“setUp()”和“tearDown()”方法。单击“Next”按钮,出现图2-5所示对话框,这里我们主要针对其关键的“add(int,int)”函数来进行测试,因此选中其前面的复选框,单击“Finish”按钮。

我们在“src”目录下,发现新创建了一个“com.yuy.calculatoroftwonum.test”包,同时Eclipse自动帮我们打开了新建的“MainActivityTest.java”文件,如图2-6所示。

为了能够让大家更清楚的看到“MainActivityTest.java”文件内容,我们将其源码贴出来,如下所示。

package com.yuy.calculatoroftwonum.test;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import android.test.AndroidTestCase;

public class MainActivityTest extends AndroidTestCase {

  @Before
  protected void setUp() throws Exception {
    super.setUp();
  }

  @After
  protected void tearDown() throws Exception {
    super.tearDown();
  }

  @Test
  public void testAdd() {
    fail("Not yet implemented");
  }

}

在生成的测试用例源文件中看到Eclipse自动帮我们创建好了3个函数,即setUp()、tearDown()和testAdd()函数。那么这些函数都是用来做什么的呢?通常setUp()函数用来完成一些初始化的工作,比如创建被测试应用实例或者我们在测试应用的业务时可能会需要登录系统,那么可以将登录放在该部分;tearDown()函数则主要完成一些收尾性的工作,比如释放对象、资源等或者系统的登出;而testAdd()函数就是我们要测试的一些方法、函数,也就是图2-6所示我们选择的测试方法,通常系统自动的帮我们在被测试的方法、函数的前面加上了一个“test”前缀,这是因为在JUnit3里,测试类必须继承TestCase类,方法必须是以“test”开头;在JUnit4里面,采用Annotation的JUnit已经不会霸道的要求必须继承自TestCase了,而且测试方法也不必以“test”开头了,只要以@Test注解来描述即可,无需继承TestCase类。JUnit 设计的非常小巧,但是功能却非常强大。Martin Fowler如此评价JUnit:在软件开发领域,从来就没有如此少的代码起到了如此重要的作用。它大大简化了开发人员执行单元测试的难度,特别是JUnit 4使用Java 5中的注解(Annotation)使测试变得更加简单。为了让大家对JUnit 4的注解有一个认识,这里我简单向大家介绍一下。

JUnit 4使用Java 5中的注解(Annotation),以下是JUnit 4常用的几个Annotation介绍。

@Before:初始化方法;

@After:释放资源;

@Test:测试方法,在这里可以设计一些测试用例,正常的、异常的测试用例;

@Ignore:忽略的测试方法;

@BeforeClass:针对所有测试,只执行一次,且必须为static void;

@AfterClass:针对所有测试,只执行一次,且必须为static void。

我们针对add()函数,想设计3个正常情况下的测试用例,如表2-1所示。当然还可以根据需要设计一些异常情况下的测试用例,因这里只是对JUnit框架的介绍,所以不予过多赘述,如果读者朋友们对此感兴趣,建议看系统的JUnit方面的书籍。

为此,我们编写的单元测试用例(MainActivityTest.java)源代码如下。

package com.yuy.calculatoroftwonum.test;
 
import com.yuy.calculatoroftwonum.MainActivity;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
 
import android.test.AndroidTestCase;
public class MainActivityTest extends AndroidTestCase {
  MainActivity myapp = null;
  @Before
  protected void setUp() throws Exception {
    super.setUp();
    myapp = new MainActivity();
  }

  @After
  protected void tearDown() throws Exception {
    super.tearDown();
    myapp = null;
  }

  @Test
  public void testAdd() {
    assertEquals(myapp.add(3,2),5);
    assertEquals(myapp.add(1,99),100);
    assertEquals(myapp.add(1,10000),10001);
  }

}

从上面的测试用例源代码中,我们能清楚的看到引入了JUnit框架的断言语句。什么叫断言呢?JUnit为我们提供了一些辅助函数,用来帮助我们确定被测试的方法是否按照预期的效果正常工作,通常把这些辅助函数称为断言。像在本测试用例源代码中使用的“assertEquals()”函数,myapp.add(3,2)是其第一个参数,它返回的是一个数字,其值应该为5,与第二个参数5是相同的,这样因为它们完全匹配,所以该断言函数的返回值为真。而后面的2个用例的断言应该也为真,关于JUnit的断言还有很多,如assertTrue()、assertNull()、assertSame()等函数,通常它们有一个明显的标记就是函数名称前面都带有“assert”。

接下来,我们要查看JUnit 4的相关库文件是否被配置,单击该项目的任意文件或者是包,而后单击鼠标右键,从快捷菜单中选择“Build Path”>“Configure Build Path …”菜单项,如图2-7所示。

请选择“Libraries”页,查看JUnit 4是否被添加,如果没有请单击“Add Library…”进行添加,如图2-8所示。

还要在“Order and Export”页查看“JUnit 4”是否被选中,如果没有被选中,则需选中该项,如图2-9所示。

而后,还需要在“AndroidManifest.xml”进行如下配置,“AndroidManifest.xml”文件的具体内容如下。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android=http://schemas.android.com/apk/res/android
  package="com.yuy.calculatoroftwonum"
  android:versionCode="1"
  android:versionName="1.0">

<uses-sdk
    android:minSdkVersion="14"
    android:targetSdkVersion="19" />

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme">

    < uses-library android:name="android.test.runner" />

<activity
      android:name=".MainActivity"
      android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

<instrumentation android:name="android.test.InstrumentationTestRunner" 
   android:targetPackage="com.yuy.calculatoroftwonum" android:label="Tests for My App" />
</manifest>

粗、黑字体部分内容为要添加的内容,即在“”增加引用“android.test.runner”的声明,如下所示。

    

,同时还需要在“”中增加“instrumentation”的信息说明,如下所示。

<instrumentation android:name="android.test.InstrumentationTestRunner"

  android:targetPackage="com.yuy.calculatoroftwonum" android:label="Tests for My App" />。

上述过程如果配置正确的话,选中“MainActivityTest.java”,单击鼠标右键,选择“Run As”>“Android JUnit Test”,如图2-10所示。

这里我们应用我的手机作为测试设备,在弹出的图2-11设备选择列表,选中我的三星手机,而后单击“OK”按钮。

我们会发现在我的手机上多了一个被测试的手机应用,如图2-12所示。

同时,还发现Eclipse自动会调出“JUnit”视图,如图2-13所示。

我们可以看到“testAdd”和“testAndroidTestCaseSetupProperly”全部执行成功,上面的进度条全为绿颜色(表示实际的结果和预期的结果一致,也就是断言为真),如果出错则显示为红颜色(表示实际的结果和预期的结果一致,也就是断言为假)。这里我们发现多出来一个“testAndroidTestCaseSetupProperly”,它是怎么来的呢?可以双击它的名称,则出现如图2-14所示信息。

我们可以看到“testAndroidTestCaseSetupProperly”隶属于“AndroidTestCase.class”类,它主要是判断是否存在上下文,因为不为空所以其为真。而双击“testAdd”则显示其相关内容,如图2-15所示。

2.3.2 JUnit基于Android项目TestSuite的应用

无论我们从事的是手工测试还是自动化测试,有的时候可能会碰到一些时间紧、任务重的情况,有的时候可能在短短的二、三十分钟后就需要将版本部署到互联网环境,无论哪种方式对我们来讲可能都是来不及完成的,此时我们就必须要评估风险,挑一些基础的、重要的业务以及与修改的缺陷相关的内容或者是优先级高的测试用例来执行。那么作为自动化测试工程师的我们又该怎样去实施呢?作为自动化测试工程师,平时在日常的工作中就要养成对自动化测试用例进行分级管理,同时不仅仅是我们要有自动化测试用例,还要有一套框架来管理测试用例按照不同的测试优先级、硬件资源利用率、甚至是结合不同的应急性测试情况手工选择要测试的内容等多种方式来执行这些自动化测试用例,并能够汇集执行结果,分发测试报告等。当然每个单位测试人员的能力不同、单位的实际情况不同、单位对测试人员的要求不同、单位对自身产品的质量要求也不同,大家要因地制宜,满足单位、研发部门、测试部门对产品的定位、产品质量的定位以及发展战略的一些要求等。言归正传,我们接着讲实施自动化测试另一个很重要的内容,测试集(Test Suite)。测试集(TestSuite)是一系列测试用例(testcase)的集合,我们可以根据需要将不同优先级、不同考察功能内容要运行的测试用例添加到测试集当中,方便测试用例的管理、执行。

下面就让我们一起来了解一下如何应用测试集。启动Eclipse,打开“CalculatorOfTwoNum”项目,然后,选中“src”,单击鼠标右键,从弹出的快捷菜单中选择“New”>“Class”,如图2-16所示。

如图2-17所示,我们将该测试集命名为“TestSuiteSample”,仍然放入“com.yuy.calculatoro- ftwonum.test”下,其父类为“junit.framework.TestSuite”,而后单击“Finish”按钮。

如图 2-18 所示为了让大家了解如何在测试集中执行多个测试用例以及如何仅执行测试用例文件中的特定的测试用例,我们再添加一个测试用例的源文件(MainActivityTest1.java),其代码如下。

package com.yuy.calculatoroftwonum.test;

import com.yuy.calculatoroftwonum.MainActivity;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import android.test.AndroidTestCase;

public class MainActivityTest1 extends AndroidTestCase {
  MainActivity myapp = null;
  @Before
  protected void setUp() throws Exception {
    super.setUp();
    myapp = new MainActivity();
  }

  @After
  protected void tearDown() throws Exception {
    super.tearDown();
    myapp = null;
  }

  @Test
  public void Add测试用例1() {
    assertEquals(myapp.add(3,2),5);
  }

  public void Addtest2() {
    assertEquals(myapp.add(3,22),26);
  }  

  public void Addtest() {
    assertEquals(myapp.add(3,2),5);
  }  
}

从上面的代码我们可以看到,我们添加了3个测试用例,即Addtest()、Add测试用例1()和Addtest2(),也许大家已经发现了2个问题,第一个问题是我们发现在用例函数的名称中包含了中文,这是可以的,如果有此需要可以这样写。第二个问题是,我们故意写错了一个断言就是Addtest2()中的“assertEquals(myapp.add(3,22),26);”本来正确的预期输出应该为“25”,这里我们却故意的写错了,期望值写成了“26”。

这里我们修改“TestSuiteSample.java”文件内容,最终其源代码如下所示。

package com.yuy.calculatoroftwonum.test;

import junit.framework.Test;
import junit.framework.TestSuite;

public class TestSuiteSample extends TestSuite {
 public static Test suite() {
  TestSuite testasuite = new TestSuite("test");
  testasuite.addTestSuite(MainActivityTest.class);
  testasuite.addTest(TestSuite.createTest(MainActivityTest1.class,"Add测试用例1"));  
  testasuite.addTest(TestSuite.createTest(MainActivityTest1.class,"Addtest2"));  
  testasuite.addTest(TestSuite.createTest(MainActivityTest1.class,"Addtest"));    
  return testasuite;
 }
}

从上面的源代码,我们不难发现" TestSuiteSample"类是从"TestSuite"中继承下来的,其定义了一个名为"suite"的静态函数,这是JUnit要求的做法,JUnit通过这种方式才能发现测试集的实际定义,接下来定义了这个测试集的名称为“test”,而TestSuite类提供了2个方法,即addTestSuite()和addTest()方法,“testasuite.addTestSuite(MainActivityTest.class);”就是“MainActivityTest”中的所有测试用例都添加到我们定义的“test”测试集中,而应用addTest()方法就可以添加特定的测试用例,比如这里我们应用“testasuite.addTest(TestSuite.createTest (MainActivityTest1.class,"Add测试用例1"));”,就将“Add测试用例1”测试用例,添加到“test”测试集中,后续用类似的方法将“Addtest2”和“Addtest”都加入到“test”测试集中。

接下来,我们选择“TestSuiteSample.java”文件,单击鼠标右键,选择“Run As”>“Android JUnit Test”菜单项,如图2-19所示。

这里我们仍然应用我的手机作为测试设备,在弹出的图2-20设备选择列表,选中我的三星手机,而后单击“OK”按钮。

我们会发现在我的手机上多了一个被测试的手机应用,如图2-21所示。

同时,还会发现Eclipse自动会调出“JUnit”视图,如图2-22所示。

我们可以看到运行显示为红色,说明有的测试用例执行是失败的,再看上方的“Runs:5/5 Errors:0 Failures:1”,表示运行了5个测试用例,失败1个,所以就为红颜色了。再往下看,下方是我的设备相关信息,在其下对应的是2个以完整的测试类命名,其下包含对应执行的该类测试用例名称,同时可以发现它们的左侧都有一个对应的状态图标,即:图片 86和图片 87。我们可以看到“com.yuy.calculatoroftwonum.MainActivityTest”下的“testAdd”和“testAndroidTestCaseSetupProperly”全部执行成功,而“com.yuy.calculatoroftwonum. MainActivityTest1”下的“Add测试用例1”和“Addtest”是执行成功的,而“Addtest2”是执行失败的,我们可以双击Addtest2,则在JUnit下方输出具体的错误信息,如图2-23所示。

时间: 2024-11-03 19:13:13

《精通移动App测试实战:技术、工具和案例》一2.3 应用JUnit对Android项目进行单元测试的相关文章

《精通移动App测试实战:技术、工具和案例》一第1章 Android系统基础内容介绍1.1 Android系统介绍

第1章 Android系统基础内容介绍 精通移动App测试实战:技术.工具和案例工欲善其事必先利其器,因为本书主要是针对移动平台讲解测试方面的内容,所以对移动平台目前主流的Android系统有一个了解十分必要,下面我们就一起来了解一下这个操作系统相关的知识内容. 1.1 Android系统介绍 Android一词的原意指"机器人",同时也是Google于2007年11月5日宣布的基于Linux平台的开源手机操作系统的名称,该平台由操作系统.中间件.用户界面和应用软件组成. Androi

《精通移动App测试实战:技术、工具和案例》一第2章 JUnit框架基础2.1 JUnit框架介绍

第2章 JUnit框架基础 精通移动App测试实战:技术.工具和案例 2.1 JUnit框架介绍 瀑布模型是最早出现的软件开发模型,如图2-1所示.该开发模型可以说在软件工程中占有重要的地位,它提供了软件开发的基本框架.其过程是从上一项活动接收该项活动的工作对象作为输入,利用这一输入实施该项活动应完成的内容,给出该项活动的工作成果,并作为输出传给下一项活动.同时评审该项活动的实施,若确认,则继续下一项活动:否则返回前面,甚至更前面的活动.对于经常变化的项目而言,瀑布模型毫无价值.然而,时至今日,

《精通移动App测试实战:技术、工具和案例》一2.2 JUnit在Android开发中的应用

2.2 JUnit在Android开发中的应用 2.2.1 单元测试的重要性 前面我们提到了单元测试,那么什么叫单元测试呢?单元测试(Unit Testing),是指对软件中的最小可测试单元进行的检查和验证.对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如在Java中单元指一个类,在C语言里单元指一个函数等.单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试.通常,我们在编写大型应用系统的时候,都要写成千上万个方法

《精通移动App测试实战:技术、工具和案例》一1.7 创建一个Android项目

1.7 创建一个Android项目 前面已经完成了Android开发环境的搭建工作,现在就让我们一起来编写一个简单的Android程序.这里我们要实现一个两个整型数字相加的程序. 1.7.1 创建一个新的Android项目 启动Eclipse,单击"File > New > Android Application Project"菜单项,如图1-42所示. 1.7.2 如何填写Android项目信息 在弹出的图1-43所示界面中,"Application Name

《精通移动App测试实战:技术、工具和案例》一1.5 搭建Android开发环境

1.5 搭建Android开发环境 基于移动平台的自动化测试,通常都需要我们有一定的语言基础.单元测试基础和IDE(Integrated Development Environment,集成开发环境).软件是用于程序开发环境的应用程序,一般包括代码编辑器.编译器.调试器和图形用户界面工具.它是集成了代码编写.编译.调试和分析等一体化的辅助开发人员开发软件的应用软件,目前应用比较广泛的IDE有VisualStudio.Eclipse等. 根据工作环境和个人喜好不同,既可以在Windows系统环境下

《精通移动App测试实战:技术、工具和案例》一1.3 Android权限系统

1.3 Android权限系统 Android操作系统其实是一个多用户的Linux操作系统,每个Android应用都使用不同的用户,运行在自己的安全沙盘里.系统为应用的所有文件设置权限,这样一来只有同一个用户的应用可以访问它们.每个应用都有自己单独的虚拟机,这样应用的代码在运行时是隔离的,即一个应用的代码不能访问或意外修改其他应用的内部数据. 每个应用都运行在单独的Linux进程中,当应用被执行时,Android都会为其启动一个Java虚拟机,因此不同的应用运行在相互隔离的环境中.Android

《精通移动App测试实战:技术、工具和案例》一1.4 Android相关的一些属性简介

1.4 Android相关的一些属性简介 Activity(活动):我们在后续的图书内容阅读过程中经常会看到这个词,那么什么是活动呢,就像我们在操作一些应用软件,比如Word,它出现的每一个功能界面,比如在编辑文件.改变字体大小后,我们单击工具条的"保存"按钮:或者是一个拼车的手机应用,我们约车的时候,其也会提供一个界面,需要我们指定出发的地点.目的地.出发时间等信息,单击"确认预约"按钮.它们都是软件系统和我们用户的一个交互,这个和我们交互的界面就叫一个"

《精通移动App测试实战:技术、工具和案例》一1.2 Android系统架构

1.2 Android系统架构 从图1-1中我们不难发现Android的系统架构采用了分层的架构,分为4个层,从高层到低层分别是应用程序层.应用程序框架层.系统运行库层和Linux内核层.那么它们每层都是用来做什么的呢? 1.应用程序层 应用层是用Java语言编写的运行在Android平台上的程序,比如一些手机游戏和基于手机端的应用等,如图1-1所示,最上面的Applications层. 2.应用程序框架层 应用程序框架层是编写Google发布的核心应用时所使用的API框架,开发人员可以使用这些

《移动App测试实战》——导读

前 言 现在已经是移动互联网的时代,借助手机等移动设备,人们可以完成资讯的获取.社交.游戏,以及日常生活的各种应用,甚至很多工作的开展.有很多新兴的移动互联网公司在崛起,也有很多传统的IT公司在转型,更有大量传统行业的企业在借助移动互联网拓展自己的业务.对IT技术人员而言,这是一个非常好的时代,有大量的工作机会,因为有大量的移动互联网相关系统的研发需求.当然,这也意味着有很多新的技术和方法要去学习.有很多的研发人员快速转型到移动互联网领域,有大量的移动互联网产品被开发出来.在这个过程中,也会面临