Android测试(基础篇)_android测试框架中,一般使用( )来测试依赖android的对象。-程序员宅基地

技术标签: junit  测试  android  工具  Android 测试  框架  eclipse  

Fundamentals(基础)

 

本文参考CodingMyWorld所译,原文地址:http://www.cnblogs.com/codingmyworld/

 

在我们学习怎样为自己的应用程序创建测试程序之前,首先要了解Android测试的基础。

Android测试框架,是集成开发环境的一部分,它提供了一个架构和强大的工具来帮助我们从单元测试到框架测试,在各个层次上全面的测试我们的应用程序。

测试框架有一下几个关键特征:

  • Android的测试套件是基于JUnit的。我们可以用原始的JUnit去测试一个没用调用Android API的类,用在JUnit上扩展的Android测试套件完成Android组件的测试。如果你是Android测试的新手,你可以从使用简单的测试用例类入手(比如AndroidTestCase),然后再使用复杂的类。
  • Android在JUnit的扩展部分中提供了特定组件的测试用例类。这些测试用例类不仅包含了创建“模拟对象”的方法,还提供了控制组件生命周期的辅助方法。
  • 测试套件包含在与应用程序包相似的测试程序包中,所以你不需要再去学习一系列为创建测试程序而使用的新设计,新技术和新工具(针对有经验的Android开发人员而言,如果你从事过Android应用程序开发,应当首先了解Android应用程序如何开发和Android应用程序结构)。
  • 在Eclipse中使用ADT工具可以建立测试并完成测试工作。ADT工具可以帮助用户自动的获取待测试应用程序的信息,创建相应的测试工程(包括代码文件,清单文件(配置文件)以及相应的包目录结构)。
  • SDK也提供的 MonkeyrRnner,一套使用Python程序测试设备的API,UI/ApplicationExerciser Monkey,一个通过向设备发送伪随机事件从而对UI压力测试的命令行工具。

这个文档的主要目的是描述Android测试框架的基础,包括测试程序的架构,用来开发测试程序的API,以及用来运行测试程序和查看查看结果的工具。此文档假定你已经对Android应用程序开发和JUnit测试方法有一些基本的认识。

下图是对测试框架的概述:

 

 

 

1       测试框架

 

Android测试程序是建立在测试工程是使用标准的测试框架,测试用例类,测试包,和测试工程的基础之上。

Android测试基于JUnit。通常,每个JUint测试实质上是一个方法,这个方法声明它是用来测试应用程序的某一部分。我们把这些JUnit测试组织到一个被称作测试用例(或者叫做测试套件)的类里面。每一个JUint测试独立地测试应用程序中单独的模块。每一个“测试用例”类里都一些相互关联的测试方法(“JUint测试”),当然也常常会有一些辅助方法。

在JUnit中,我们把测源代码写在一个类文件里;与之类似,我们通过Android SDK的构建工具,把一个或多个测试代码放在Androi测试包的类文件中。在JUnit里,我们使用测试运行器执行测试用例;在Android中,我们使用测试工具加载测试包和待测试应用程序,然后测试工具执行Android专用的测试运行器完成测试。

 

2       测试项目(Test Projects)

 

测试,像Android应用程序一样,被组织成项目(Project)。

一个测试项目就是一个Eclipse项目,这个项目里我们可以编写测试代码、清单文件(Manifest File),和测试需要用到的其他文件。Google为我们提供的ADT工具可以创建和更新测试项目,由ADT工具完成创建存放源代码的目录、以及测试项目的资源文件和清单文件(ManifestFile)。

我应当总是使用Android工具去创建一个测试项目。使用工具有以下几点优势,:

  • 自动设置 InstrumentationTestRunner作为测试包的测试运行器。我们必须使用 InstrumentationTestRunner(或它的子类)运行测试用例。
  • 为测试包起一个合适的名字。如果待测试应用程序有的包命为com.mydomain.myapp,则测试项目的包名为com.mydomain.myapp.test。这有助于分辨两者的关系,避免在系统中产生冲突。
  • 自动为测试项目建立合适构建文件、清单文件(manifestfile) 以及目录结构。这有助于我们建立测试项目,不必通过修改构建文件来设置测试项目和待测试项目之间的关联。

我们可以在计算机的任意位置创建测试项目,但是最好的方式是在被测试的项目目录中,新建一个tests/目录,并把代码放在tests/目录下面。tests/目录要与src/目录在同一层中。例如,如果你的应用程序项目的根目录是MyProject,那你目录结构应当像下面这样:

 

3       测试用API(The Test API)

 

Android的测试API是基于JUnit API的,并且在此基础上,开发了instrumentation框架和一些Android专用的测试类。

 

JUnit

 

你可以使用JUnit 的TestCase类去测试一个纯Java对象。TestCase也是AndriodTestCase的基类,AndroidTestCase类是用来测试依赖Android的对象。除了提供JUnit框架的功能外,AndroidTestCase还提供了Andriod系统专用的安装、销毁和一些辅助方法。

你可以使用JUnit的Assert类输出(display)测试结果。Assert的方法比较实际值与期望值,如果两者比较失败则抛出异常。同时android也提供了其他类型的比较方法,和另一类用来测试UI的断言。

我们必须使用Android提供的测试运行器——InstrumentationTestRunner运行我们的测试用例。

 

装配或仪器(Instrumentation)

 

Android的instrumentation是指Android系统中一系列的控制方法或“钩子(Hooks)”,这些“钩子(hooks)”可以独立地控制一个Android组件的生命周期,也就是控制着Android怎样去加载一个应用程序。

通常情况下,一个android组件的生命周期如何运作是由系统决定的。例如,一个Activity对象的生命周,开始于这个Activity被Intent启动,然后onCreate()方法被调用,接着是onResume();当用户启动另一个应用时,onPause()方法被调用;如果Activity调用了finish()方法,onDestroy()方法被调用。这些都工作都是由Android系统完成,开发者不能通过Android框架直接调用这些方法,但是通过Instrumentation可以做到。

与上面类似,Android系统中同一个应用程序的所有组件运行在同一个进程里。你可以通过Instrumentation把某一个或某几个组件放在在其他的进程里运行。但是你不能在一个已经有应用程序运行的进程中强迫运行另一个应用程序。

通过Android的Instrumentation,你可以在测试代码中调用回调函数。它允许你一步一步地运行组件的生命周期,就像在调试应用程序一样。下图的代码展示了如何使用Instrumentation保存和恢复一个Activity的状态。

这里使用的关键方法是 getActivity(),它是Instrumentation API中的一个方法。在测试环境下如果你不调用此方法,Activity是不会自动启动的。你应当事先设置好测试环境,然后调用此方法启动Activity。

Instrumentation能够把测试程序和待测试应用程序同时加载到一个进程中;这样当测试程序与待测试应用程序运行在同一个进程中时,测试程序就可以调用应用程序的组件里的各种方法,修改、测试这些组件的属性值。

 

测试用例类(Test Case Classes)

 

Android提供了多个测试用例类,这些测试用例类继承自TestCase和Assert类,并实现了Andorid特定的setup、teardown和一些辅助方法。

 

Component-specific test cases(特定组件测试用例)

 

Android测试框架的一个关键特征是,它提供了一些组件专用的测试用例类,满足我们对特定组件测试的需求。组件专用测试用例的方法,实现组件安装(setup),销毁(teardown)等生命周期的控制,也提供了设置模拟对象的方法,更详细的内容可以阅读“组件专用测试”章节。

Android没有提供专门的用于测试BroadcastReceiver组件的测试用例类。我们可以通过测试组件发出Intent请求后BroadcaseReceiver是否做出了正确相应的方式去测试BroadcaReceiver组件。

 

ApplicationTestCase

 

ApplicationTestCase测试用例类是用来测试Application对象的安装(setup)和销毁(teardown),Application对象维护着应用程序组件要用到的一些全局变量和状态信息。ApplicationTestCase测试用例类能帮助我们判断Application是否被正确的设置。注意:此测试类不能控制应用程序中组件的测试。

 

InstrumentationTestCase

 

如果你需要在测试用例类里使用Instrumentation的方法,你必须使用InstrumentationTestCase类或者它的子类。Activity测试用例类就是以它为基类进行扩展,实现了协助完成Activity测试的功能。

 

断言类(Assertion Class)

 

因为Android测试用例类继承自JUnit,所以你能使用断言方法(Assertion)输出测试的结果。一个断言方法(Assertion)会判断实际返回值是否与期望值相同,如果不同则抛出异常。使用断言比打印日志更方便,而且能提高测试的效率。

除了JUnit的断言外,Android测试框架还提供了MoreAsserts和ViewAsserts类:

  • MoreAsserts包含了其他许多功能强大的断言,assertContainRegex(String,String)方法,它可以判断字符串与正则表达式是否匹配。
  • ViewAsserts包含了用于测试View的有用的方法。比如,它的assertHasScreenCoordinates(View,Vie,int,int)方法,用它可以测试一个View是否在屏幕的可见区域上的(x,y)位置上。这个断言方法简单的测试UI中的几何尺寸和是否对齐。

 

Mock object classes(模拟对象类)

 

为了在测试中更方便的使用依赖注入,Android提供用来创建“模拟系统对象”的类,比如模拟Context对象,模拟ContentProvider对象,模拟ContentResolver对象,或是模拟Service对象。某些测试用例中可能还会提供模拟Intent对象。我们使用这些模拟对象既可以使测试独立于系统的其他部分,也可以方便的为测试进行依赖注入。这些类可以在java包android.test和android.test.mock下找到。

模拟对象可以屏蔽、覆盖常规操作,使你的测试测试程序与正在运行的系统隔离。例如,一个MockContentResolver对象使用自己的本地的Resolver框架取代常规的resolver框架,也就把MockContentResolver对象隔离在系统的其他部分之外,MockContentResolver也屏蔽了notifyChange(Uri,ContentObserver,Boolean)方法,这样在测试环境之外的Observer对象就不会被意外的触发。

模拟对象类还通过提供常规对象的子类来方便依赖注入,这个子类没有任何实际的功能,除非你重写了父类的方法。例如,MockResources类提供了一个的Resources的子类,它的所有的方法在被调用时都会抛出异常。如果你要使用它,你需重写那些供必须信息的方法。

这里有一些android提供的虚拟对象类:

 

简单的模拟对象类(Simple mock object classes)

 

MockAppplication,MockContext,MockContentProvider,MockCursor,MockDialogInterface,MockPackageManager和MockResourse 提供了一个简单且有用的模拟策略。这些类是它们相关的系统对象类的屏蔽版,如果你调用他们的方法,它们会抛出UnsupportedOperationException异常;如果你要使用这些类的方法,你需要自己去重写这些方法。

 

Resolver mock objects

 

MockContentResolver使用一个测试用的content provider隐藏了系统常规的resolver框架。你不需要在系统去寻找某个content provider的授权口令,取而代之的是你调用addProvider(String,ContentProvider)添加Privider到MockContentProvider自己的内部数据表中。

使用这个特性,你可以将一个content provider和某个授权字符串关联在一起。这样一来你就能够创建一个真实存在的provider的实例,但使用的是测试数据。你甚至可以把一个空的授权字符串关联到provider对象上。实际上,MockContentProvider对象把我们的测试与含有真实数据的Provider隔离开,这样我们能够控制Provider的功能,又不影响真实数据。

 

Contexts for testing

 

Android提供了两个十分有用的测试Context的类:

  • IsolatedContext提供了一个隔离的Context。使用该Context的文件,目录,和数据库操作只在测试区域内起作用。尽管它的功能收到限制的,但是它有足够的代码响应系统调用。

这个类能够让你在测试应用程序的数据操作时,不影响到当前设备的真实数据。

  • RenamingDelegationContext提供了一个Context,其中的大部分方法使用已经存在的Context处理,但是文件和数据库操作仍是由IsolateContext处理。隔离部分使用测试目录,使用指定的文件和目录名。你可以自己控制文件的命名,也可以让构造器自己决定如何命名。

这个对象提供了为数据操作快速设置测试隔离区的方法,同时又确保其他Context功能的正常使用。

 

4       运行测试(Running Tests)

 

测试用例需要一个测试运行器类运行,这个运行器类负责加载、配置、运行和销毁每一个测试用例。Android测试运行器也是必须被装配(instrumented)的,这样用来启动应用程序的系统程序便可以控制测试包如何加载测试用例和待测试应用程序。你可以通过设置测试包的清单文件(manifest file),告诉Android平台使用哪个被装配的测试运行器。

InstrumentationTestRunner是Android的主要测试测试运行器类,它集成自JUnit的测试运行器框架,同时它也是能被装配(instrumented)的。它可以运行任何由Android提供的测试用例,支持所有可能的测试种类。

你在测试包的清单文件(manifest file)的instrument元素中,指定InstrumentationTestRunner类或者一个它的子类。InstrumentationTestRunner的代码在共享函数库android.test.runner中,但是通常没有链接到android代码中。为了将它包含进来,你必须在users-library元素设置。你不必亲自动手去设置这些元素,因为Eclipse的ADT工具会帮你完成测试包的manifest文件的配置工作,把这些元素添加到清单文件(manifest file)中。

注意:如果你不使用InstrumentationTestRunner作为测试运行器,你必须在清单文件(manifestfile)中重新配置<instrumentation>元素,让它指向你想用测试运行器。

你需要用Android工具去调用内部系统类运行InstrumentationTestRunner。当你使用Eclipse的ADT工具时,ADT会自动帮你完成调用内部系统类。

系统类加载并启动你的测试包,然后检测待测试程序是否在运行,如果待测试程序正在运行,系统将杀死运行待测试程序的进程,接着生成此待测试程序的新实例并将其加载到测试进程中。系统将控制权交给InsrumentationTestRunner,由InstrumentationTestRunner运行测试包中的所有测试用例。通过ADT工具你可以指定运行测试包中的哪个测试用例或测试用例的哪个方法。

待测试应用程序,既不是由系统类也不是由InstrumentationTestRunner在操作,而是由用测试用例直接操作。测试用例既调用应用程序的方法,又通过调用自己的方法触发应用程序的生命周期事件。应用程序完全在测试用例的控制之下,测试用例在运行测试之前,会事先配置好测试环境。

 

5       观察测试结果(Seeing Test Result)

 

Android测试框架将把测试结果返回给启动测试的工具,如果你使用Eclipse的ADT工具启动的测试,那测试结果将显示到JUnit视图窗口中。在测试结果摘要里,你可以看到测试用例的名字和哪些测试方法被运行。你还可以看到所有产生失败的断言的信息:包括指向在测试代码中发生错误的所在行号,列出了失败断言的期望值和实际值。

 

6       正确处理包名(Working With Package names)

 

在Android测试环境中,我们需要处理好Android应用程序包名和Java包名;两者虽然使用相同的命名格式,却表示两个不同的实体。我们需要了解两者的区别,以便能正确的设置我的测试程序。

Android包名是一个.apk文件在系统中的唯一标示符,在应用程序包中的清单文件(manifest file)的<manifest>元素的“android:package”属性中设置。测试程序的包名必须与待测试程序的包名不同,在默认情况下,Android工具会自动在待测试程序的包名后面加上“.test”作为测试程序的包名。

测试程序包里的清单文件(manifest file)的<instrumentation>元素的“android:targetPackage”属性,用来设置此测试程序的目标程序。

Java包名指向源文件,这个包名反映的是源文件的路径。同时它也影响到类之间、成员之间的可见性。

辅助我们创建测试项目的工具会帮我们起一个Android测试程序的包名。根据我们的输入,工具会帮我们设置好测试程序的包名和待测试程序的包命。当然前提是待测试程序的项目已经存在(注意这里不是指.apk文件,而是应用程序项目)。

默认情况下,这些工具把测试类的Java包名与测试包的Android包名设置成一样的。如果你想要给它们包可见性,从而在待测应用中暴露出一些成员,你可能需要做些改动。假如你真要这么做了,请你只改动Java的包名,不要改动Android包名,并且只改变测试用例类的源文件。不要改变在你测试包中生成的R.java类的Java包名。不要将测试包的Android包名改成与待测应用的Android包名一样,因为这样的话系统中的Android包名就不是唯一的了。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/luyi_alpha/article/details/7195542

智能推荐

oracle 12c 集群安装后的检查_12c查看crs状态-程序员宅基地

文章浏览阅读1.6k次。安装配置gi、安装数据库软件、dbca建库见下:http://blog.csdn.net/kadwf123/article/details/784299611、检查集群节点及状态:[root@rac2 ~]# olsnodes -srac1 Activerac2 Activerac3 Activerac4 Active[root@rac2 ~]_12c查看crs状态

解决jupyter notebook无法找到虚拟环境的问题_jupyter没有pytorch环境-程序员宅基地

文章浏览阅读1.3w次,点赞45次,收藏99次。我个人用的是anaconda3的一个python集成环境,自带jupyter notebook,但在我打开jupyter notebook界面后,却找不到对应的虚拟环境,原来是jupyter notebook只是通用于下载anaconda时自带的环境,其他环境要想使用必须手动下载一些库:1.首先进入到自己创建的虚拟环境(pytorch是虚拟环境的名字)activate pytorch2.在该环境下下载这个库conda install ipykernelconda install nb__jupyter没有pytorch环境

国内安装scoop的保姆教程_scoop-cn-程序员宅基地

文章浏览阅读5.2k次,点赞19次,收藏28次。选择scoop纯属意外,也是无奈,因为电脑用户被锁了管理员权限,所有exe安装程序都无法安装,只可以用绿色软件,最后被我发现scoop,省去了到处下载XXX绿色版的烦恼,当然scoop里需要管理员权限的软件也跟我无缘了(譬如everything)。推荐添加dorado这个bucket镜像,里面很多中文软件,但是部分国外的软件下载地址在github,可能无法下载。以上两个是官方bucket的国内镜像,所有软件建议优先从这里下载。上面可以看到很多bucket以及软件数。如果官网登陆不了可以试一下以下方式。_scoop-cn

Element ui colorpicker在Vue中的使用_vue el-color-picker-程序员宅基地

文章浏览阅读4.5k次,点赞2次,收藏3次。首先要有一个color-picker组件 <el-color-picker v-model="headcolor"></el-color-picker>在data里面data() { return {headcolor: ’ #278add ’ //这里可以选择一个默认的颜色} }然后在你想要改变颜色的地方用v-bind绑定就好了,例如:这里的:sty..._vue el-color-picker

迅为iTOP-4412精英版之烧写内核移植后的镜像_exynos 4412 刷机-程序员宅基地

文章浏览阅读640次。基于芯片日益增长的问题,所以内核开发者们引入了新的方法,就是在内核中只保留函数,而数据则不包含,由用户(应用程序员)自己把数据按照规定的格式编写,并放在约定的地方,为了不占用过多的内存,还要求数据以根精简的方式编写。boot启动时,传参给内核,告诉内核设备树文件和kernel的位置,内核启动时根据地址去找到设备树文件,再利用专用的编译器去反编译dtb文件,将dtb还原成数据结构,以供驱动的函数去调用。firmware是三星的一个固件的设备信息,因为找不到固件,所以内核启动不成功。_exynos 4412 刷机

Linux系统配置jdk_linux配置jdk-程序员宅基地

文章浏览阅读2w次,点赞24次,收藏42次。Linux系统配置jdkLinux学习教程,Linux入门教程(超详细)_linux配置jdk

随便推点

matlab(4):特殊符号的输入_matlab微米怎么输入-程序员宅基地

文章浏览阅读3.3k次,点赞5次,收藏19次。xlabel('\delta');ylabel('AUC');具体符号的对照表参照下图:_matlab微米怎么输入

C语言程序设计-文件(打开与关闭、顺序、二进制读写)-程序员宅基地

文章浏览阅读119次。顺序读写指的是按照文件中数据的顺序进行读取或写入。对于文本文件,可以使用fgets、fputs、fscanf、fprintf等函数进行顺序读写。在C语言中,对文件的操作通常涉及文件的打开、读写以及关闭。文件的打开使用fopen函数,而关闭则使用fclose函数。在C语言中,可以使用fread和fwrite函数进行二进制读写。‍ Biaoge 于2024-03-09 23:51发布 阅读量:7 ️文章类型:【 C语言程序设计 】在C语言中,用于打开文件的函数是____,用于关闭文件的函数是____。

Touchdesigner自学笔记之三_touchdesigner怎么让一个模型跟着鼠标移动-程序员宅基地

文章浏览阅读3.4k次,点赞2次,收藏13次。跟随鼠标移动的粒子以grid(SOP)为partical(SOP)的资源模板,调整后连接【Geo组合+point spirit(MAT)】,在连接【feedback组合】适当调整。影响粒子动态的节点【metaball(SOP)+force(SOP)】添加mouse in(CHOP)鼠标位置到metaball的坐标,实现鼠标影响。..._touchdesigner怎么让一个模型跟着鼠标移动

【附源码】基于java的校园停车场管理系统的设计与实现61m0e9计算机毕设SSM_基于java技术的停车场管理系统实现与设计-程序员宅基地

文章浏览阅读178次。项目运行环境配置:Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。项目技术:Springboot + mybatis + Maven +mysql5.7或8.0+html+css+js等等组成,B/S模式 + Maven管理等等。环境需要1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。_基于java技术的停车场管理系统实现与设计

Android系统播放器MediaPlayer源码分析_android多媒体播放源码分析 时序图-程序员宅基地

文章浏览阅读3.5k次。前言对于MediaPlayer播放器的源码分析内容相对来说比较多,会从Java-&amp;amp;gt;Jni-&amp;amp;gt;C/C++慢慢分析,后面会慢慢更新。另外,博客只作为自己学习记录的一种方式,对于其他的不过多的评论。MediaPlayerDemopublic class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal..._android多媒体播放源码分析 时序图

java 数据结构与算法 ——快速排序法-程序员宅基地

文章浏览阅读2.4k次,点赞41次,收藏13次。java 数据结构与算法 ——快速排序法_快速排序法