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

智能推荐

分布式光纤传感器的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告_预计2026年中国分布式传感器市场规模有多大-程序员宅基地

文章浏览阅读3.2k次。本文研究全球与中国市场分布式光纤传感器的发展现状及未来发展趋势,分别从生产和消费的角度分析分布式光纤传感器的主要生产地区、主要消费地区以及主要的生产商。重点分析全球与中国市场的主要厂商产品特点、产品规格、不同规格产品的价格、产量、产值及全球和中国市场主要生产商的市场份额。主要生产商包括:FISO TechnologiesBrugg KabelSensor HighwayOmnisensAFL GlobalQinetiQ GroupLockheed MartinOSENSA Innovati_预计2026年中国分布式传感器市场规模有多大

07_08 常用组合逻辑电路结构——为IC设计的延时估计铺垫_基4布斯算法代码-程序员宅基地

文章浏览阅读1.1k次,点赞2次,收藏12次。常用组合逻辑电路结构——为IC设计的延时估计铺垫学习目的:估计模块间的delay,确保写的代码的timing 综合能给到多少HZ,以满足需求!_基4布斯算法代码

OpenAI Manager助手(基于SpringBoot和Vue)_chatgpt网页版-程序员宅基地

文章浏览阅读3.3k次,点赞3次,收藏5次。OpenAI Manager助手(基于SpringBoot和Vue)_chatgpt网页版

关于美国计算机奥赛USACO,你想知道的都在这_usaco可以多次提交吗-程序员宅基地

文章浏览阅读2.2k次。USACO自1992年举办,到目前为止已经举办了27届,目的是为了帮助美国信息学国家队选拔IOI的队员,目前逐渐发展为全球热门的线上赛事,成为美国大学申请条件下,含金量相当高的官方竞赛。USACO的比赛成绩可以助力计算机专业留学,越来越多的学生进入了康奈尔,麻省理工,普林斯顿,哈佛和耶鲁等大学,这些同学的共同点是他们都参加了美国计算机科学竞赛(USACO),并且取得过非常好的成绩。适合参赛人群USACO适合国内在读学生有意向申请美国大学的或者想锻炼自己编程能力的同学,高三学生也可以参加12月的第_usaco可以多次提交吗

MySQL存储过程和自定义函数_mysql自定义函数和存储过程-程序员宅基地

文章浏览阅读394次。1.1 存储程序1.2 创建存储过程1.3 创建自定义函数1.3.1 示例1.4 自定义函数和存储过程的区别1.5 变量的使用1.6 定义条件和处理程序1.6.1 定义条件1.6.1.1 示例1.6.2 定义处理程序1.6.2.1 示例1.7 光标的使用1.7.1 声明光标1.7.2 打开光标1.7.3 使用光标1.7.4 关闭光标1.8 流程控制的使用1.8.1 IF语句1.8.2 CASE语句1.8.3 LOOP语句1.8.4 LEAVE语句1.8.5 ITERATE语句1.8.6 REPEAT语句。_mysql自定义函数和存储过程

半导体基础知识与PN结_本征半导体电流为0-程序员宅基地

文章浏览阅读188次。半导体二极管——集成电路最小组成单元。_本征半导体电流为0

随便推点

【Unity3d Shader】水面和岩浆效果_unity 岩浆shader-程序员宅基地

文章浏览阅读2.8k次,点赞3次,收藏18次。游戏水面特效实现方式太多。咱们这边介绍的是一最简单的UV动画(无顶点位移),整个mesh由4个顶点构成。实现了水面效果(左图),不动代码稍微修改下参数和贴图可以实现岩浆效果(右图)。有要思路是1,uv按时间去做正弦波移动2,在1的基础上加个凹凸图混合uv3,在1、2的基础上加个水流方向4,加上对雾效的支持,如没必要请自行删除雾效代码(把包含fog的几行代码删除)S..._unity 岩浆shader

广义线性模型——Logistic回归模型(1)_广义线性回归模型-程序员宅基地

文章浏览阅读5k次。广义线性模型是线性模型的扩展,它通过连接函数建立响应变量的数学期望值与线性组合的预测变量之间的关系。广义线性模型拟合的形式为:其中g(μY)是条件均值的函数(称为连接函数)。另外,你可放松Y为正态分布的假设,改为Y 服从指数分布族中的一种分布即可。设定好连接函数和概率分布后,便可以通过最大似然估计的多次迭代推导出各参数值。在大部分情况下,线性模型就可以通过一系列连续型或类别型预测变量来预测正态分布的响应变量的工作。但是,有时候我们要进行非正态因变量的分析,例如:(1)类别型.._广义线性回归模型

HTML+CSS大作业 环境网页设计与实现(垃圾分类) web前端开发技术 web课程设计 网页规划与设计_垃圾分类网页设计目标怎么写-程序员宅基地

文章浏览阅读69次。环境保护、 保护地球、 校园环保、垃圾分类、绿色家园、等网站的设计与制作。 总结了一些学生网页制作的经验:一般的网页需要融入以下知识点:div+css布局、浮动、定位、高级css、表格、表单及验证、js轮播图、音频 视频 Flash的应用、ul li、下拉导航栏、鼠标划过效果等知识点,网页的风格主题也很全面:如爱好、风景、校园、美食、动漫、游戏、咖啡、音乐、家乡、电影、名人、商城以及个人主页等主题,学生、新手可参考下方页面的布局和设计和HTML源码(有用点赞△) 一套A+的网_垃圾分类网页设计目标怎么写

C# .Net 发布后,把dll全部放在一个文件夹中,让软件目录更整洁_.net dll 全局目录-程序员宅基地

文章浏览阅读614次,点赞7次,收藏11次。之前找到一个修改 exe 中 DLL地址 的方法, 不太好使,虽然能正确启动, 但无法改变 exe 的工作目录,这就影响了.Net 中很多获取 exe 执行目录来拼接的地址 ( 相对路径 ),比如 wwwroot 和 代码中相对目录还有一些复制到目录的普通文件 等等,它们的地址都会指向原来 exe 的目录, 而不是自定义的 “lib” 目录,根本原因就是没有修改 exe 的工作目录这次来搞一个启动程序,把 .net 的所有东西都放在一个文件夹,在文件夹同级的目录制作一个 exe._.net dll 全局目录

BRIEF特征点描述算法_breif description calculation 特征点-程序员宅基地

文章浏览阅读1.5k次。本文为转载,原博客地址:http://blog.csdn.net/hujingshuang/article/details/46910259简介 BRIEF是2010年的一篇名为《BRIEF:Binary Robust Independent Elementary Features》的文章中提出,BRIEF是对已检测到的特征点进行描述,它是一种二进制编码的描述子,摈弃了利用区域灰度..._breif description calculation 特征点

房屋租赁管理系统的设计和实现,SpringBoot计算机毕业设计论文_基于spring boot的房屋租赁系统论文-程序员宅基地

文章浏览阅读4.1k次,点赞21次,收藏79次。本文是《基于SpringBoot的房屋租赁管理系统》的配套原创说明文档,可以给应届毕业生提供格式撰写参考,也可以给开发类似系统的朋友们提供功能业务设计思路。_基于spring boot的房屋租赁系统论文