Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Android Unit Testing
Search
Sylvain W
June 26, 2015
170
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Android Unit Testing
Sylvain W
June 26, 2015
Featured
See All Featured
Statistics for Hackers
jakevdp
799
230k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
930
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
350
WENDY [Excerpt]
tessaabrams
11
39k
We Are The Robots
honzajavorek
0
290
Docker and Python
trallard
47
4k
Discover your Explorer Soul
emna__ayadi
2
1.2k
Building an army of robots
kneath
306
46k
Mind Mapping
helmedeiros
PRO
1
290
GitHub's CSS Performance
jonrohan
1033
470k
How to Talk to Developers About Accessibility
jct
2
450
Ten Tips & Tricks for a 🌱 transition
stuffmc
0
160
Transcript
单元测试 王思远
提纲 单元测试 JUnit测试框架 通过反射测试私有成员 Android Studio测试
单元测试 在计算机编程中,单元测试(又称为模块测试, Unit Testing)是针 对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。 程序单元是应用的最小可测试部件。在过程化编程中,⼀个单元就 是单个程序、函数、过程等;对于面向对象编程,最小单元就是方 法,包括基类(超类)、抽象类、或者派生类(子类)中的方法。
通常来说,程序员每修改⼀次程序就会进行最少⼀次单元测试。虽 然单元测试不是什么必须的,但也不坏,这牵涉到项目管理的政策 决定。
单元测试 单元测试其实是相对廉价而简单的技术,但它能让你更高效地写出 质量更好的代码。 说到测试,大凡组织和个人都会满怀雄心壮志,但是往往只是在项 目快要结束的时候才想起测试。而那时的进度压力⼀定非常紧迫, 所以结果往往只是浅尝辄止或者干脆就不测试了,这样就起不到预 防缺陷的意义。
当基本的底层代码不再可靠时,那么必需的改动就无法只局限在底 层,虽然你可以修正底层的问题,但是这对底层代码的修改必然会 影响到高层代码,于是高层代码也连带地需要修改;以此递推,就 很可能会动到更高层的代码。于是,⼀个对底层代码的修正,可能 会导致对几乎所有代码的⼀连串改动,从而使修改越来越多,也越 来越复杂。项目中存在的风险越来越高,导致整个项目的失败的可 能性也越来越大。 简而言之,在有些时候,使用单元测试本身就能决定你的项目的成 败。
单元测试:生产率 从长远看来,使用“立即测试模型”的代价比“延后测试模型”的 代价要低。在你编写实现代码的时候,同时编写独立的测试代码, 在项目最后就可以避免出现做了无用功的问题;代码中的bug也会 更少,因为你所依赖的都是已经测试的代码。于是,通过在开发过 程中多花⼀点时间在编写单元测试上面,你就可以在最小化在项目 后期花费大量时间的风险。
单元测试:收益 单元测试的目标是隔离程序部件并证明这些单个部件是正确的。⼀ 个单元测试提供了代码片断需要满足的严密的书面规约。因此,单 元测试带来了⼀些益处。 单元测试在软件开发过程的早期就能发现 问题。 1. 适应变更:单元测试允许程序员在未来重构代码,并且确保模块依然工作正确(复 合测试)。这个过程就是为所有函数和方法编写单元测试,⼀旦变更导致错误发生,
借助于单元测试可以快速定位并修复错误。 2. 简化集成:单元测试消除程序单元的不可靠,采用自底向上的测试路径。通过先测 试程序部件再测试部件组装,使集成测试变得更加简单。 3. 文档记录:单元测试提供了系统的⼀种文档记录。借助于查看单元测试提供的功能 和单元测试中如何使用程序单元,开发人员可以直观的理解程序单元的基础API。
单元测试:测试范畴 它的行为和我期望的⼀致吗? 这是单元测试最根本的目的,我们就是用单元测试的代码来证明它所做的就是我们 所期望的。 它的行为⼀直和我期望的⼀致吗? 编写单元测试,如果只测试代码的⼀条正确路径,让它正确走⼀遍,并不算是真正 的完成。 软件开发是⼀个项复杂的工程,在测试某段代码的行为是否和你的期望⼀致时,你
需要确认:在任何情况下,这段代码是否都和你的期望⼀致;譬如参数很可疑、硬 盘没有剩余空间、缓冲区溢出、网络掉线的时候。 我可以依赖单元测试吗? 不能依赖的代码是没有多大用处的。既然单元测试是用来保证代码的正确性,那么 单元测试也⼀定要值得依赖,并且清楚地知道这些代码的功能和约束。 单元测试说明我的意图了吗? 单元测试能够帮我们充分了解代码的用法,从效果上而言,单元测试就像是能执行 的文档,说明了在你用各种条件调用代码时,你所能期望这段代码完成的功能。
JUnit单元测试 JUnit是⼀个开发源代码的Java测试框架,用于编写和运行可重复的 测试。它是用于单元测试框架体系xUnit的⼀个实例(用于java语 言)。主要用于白盒测试,回归测试。 JUnit特征: 1. 提供的API可以写出测试结果明确的可重用单元测试用例。 2.
提供了测试结果的显示,而且还可以扩展。 3. 提供了单元测试用例成批运行的功能。 4. 超轻量级而且使用简单,没有商业性的欺骗和无用的向导。 5. 整个框架设计良好,易扩展。
JUnit单元测试 JUnit框架组成: 1. 对测试目标进行测试的方法与过程集合,可称为测试用例(TestCase)。 2. 测试用例的集合,可容纳多个测试用例(TestCase),将其称作测试包(TestSuite)。 3. 测试结果的描述与记录(TestResult) 。
4. 测试过程中的事件监听者(TestListener)。 5. 每⼀个测试方法所发生的与预期不⼀致状况的描述,称其测试失败元素(TestFailure)。 6. JUnit Framework中的出错异常(AssertionFailedError)。
JUnit单元测试 Test接口:运行测试和收集测试结果 1. Test接口是单独测试用例(TestCase),聚合测试模式(TestSuite)及测试扩展 (TestDecorator)的共同接口。 2. 它的public int countTestCases()方法,用来统计测试时有多少个TestCase。
3. 另外⼀个方法就是public void run(TestResult),TestResult是实例接受测试结果,run 方法执行本次测试。 TestCase抽象类:定义测试中固定方法 1. TestCase是Test接口的抽象实现,其构造函数TestCase(string name)根据输入的测试 名称name创建⼀个测试实例。 2. TestCase在创建时都要有⼀个名称,若测试失败了,便可识别出是哪个测试失败。 3. TestCase类中包含的setUp()、tearDown()方法。 4. setUp()方法集中初始化测试所需的所有变量和实例,并且在依次调用测试类中的每 个测试方法之前再次执行setUp()方法。 5. tearDown()方法则是在每个测试方法之后,释放测试程序方法中引用的变量和实例。 6. 编写测试用例时,只需继承TestCase,来完成run方法即可,然后JUnit获得测试用例, 执行它的run方法,把测试结果记录在TestResult之中。
JUnit单元测试 Assert静态类:⼀系列断言方法的集合 Assert包含了⼀组静态的测试方法,用于期望值和实际值比对是否正确,即测试失败, Assert类就会抛出⼀个AssertionFailedError异常,JUnit测试框架将这种错误归入 Fails并加以记录,同时标志为未通过测试。 assertTrue 断言条件为真。 assertFalse 断言条件为假。
assertEquals 断言两个对象相等。 assertNotNull 断言对象不为null。 assertNull 断言对象为null。 assertSame 断言两个引用指向同⼀个对象。 assertNotSame 断言两个引用指向不同的对象。 fail 让测试失败,并给出指定的信息。
JUnit单元测试 TestResult结果类和其它类与接口 1. TestResult结果类集合了任意测试累加结果,通过TestResult实例传递个每个测试的 Run()方法。TestResult在执行TestCase时如果失败会异常抛出。 2. TestListener接口是个事件监听规约,可供TestRunner类使用。它通知listener的对象 相关事件,方法包括测试开始startTest(Test test),测试结束endTest(Test
test),错误, 增加异常addError(Test test,Throwable t)和增加失败addFailure(Test test,AssertionFailedError t)。 3. TestFailure失败类是个“失败”状况的收集类,解释每次测试执行过程中出现的异 常情况。其toString()方法返回“失败”状况的简要描述。
JUnit单元测试 JUnit测试框架目前主要有两种(JUnit3.8和JUnit4.x)。主要介绍 JUnit3.8的用法。 涉及到的包⼀般是 import junit.framework.* 在
JUnit 3.8 中,测试类要继承TestCast类,而TestCast类又继承于 Assert类,测试方法需满足如下原则: 1. 修饰符设为 public 2. 返回类型 void 3. 没有方法参数 4. 方法名称必须以test开头 5. 测试类都继承于TestCase类 另外,使用过程中,测试类不能依赖于测试方法的执行顺序。
JUnit单元测试 在新建的测试类中,有两个方法需要强调⼀下: setUp方法和tearDown方法,都是TestCase类的方法 1. setUp方法是在执行每个测试方法之前执行的,可以做⼀些初始化的工作,例如类 实例声明。 2. tearDown方法是在执行每个测试方法之后执行的,例如在此销毁对象。
JUnit单元测试:实例
JUnit单元测试:实例
None
JUnit单元测试:实例 本例中只对加减乘除计算设计了基本的测试方法,并未对目标类进 行全面的测试,实际的测试中应该对目标类中的方法进行全面的测 试。 例如,对+方法的测试,除了基本的两数相加,也许还应该设计: 1. 如果传入两个浮点型参数进行add运算 2.
如果传入两个数值的和越界怎么办 3. 还有许多其他情景需要测试
JUnit单元测试:测试套件 如果测试类多了,单个单个的这个测试方式效率不尽如人意。使用 运行测试套件,对整个测试类进行执行测试。
通过反射测试私有成员 测试私有(private)的方法有两种: 1. 把目标类的私有方法修饰符private修改为public,不推荐,因为这样修改了源程序。 2. 通过反射 (推荐)。 反射的常用函数:
1. getDeclaredConstructor 2. getDeclaredMethod 3. getDeclaredField 假设目标程序是:
通过反射测试私有成员
通过反射测试私有成员:内部类 在Calculator类中新增内部类: 在测试代码中新增测试方法:
Android测试 Android测试套件是基于JUnit的。 可以使用普通的JUnit测试(TestCase)来对不需要调用Andriod API的类进行测试。 或者使用Android's JUnit extensions来对Android组件进行测试。
Android仪表(Instrumentation)能够获取⼀系列系统信息,包括gc 次数,分配对象和内存数量,释放对象和内存数量等。 1. ApplicationTestCase:主要用来测试Application,提供了对Application类生命周期方 法的基本支持,可以支持注入⼀些mock context对象等。测试时是要将app运行起来 的。 2. ActivityInstrumentationTestCase2:当前主流用于测试apps功能的测试类,大名鼎鼎 的robotium就是基于这个类来实现的。提供Activity生命周期支持,也需要将app运 行起来,同事可以通过instrumentation来获取系统信息。 3. ActivityUnitTestCase:为了单独测试Activity而存在,会以与系统底层关联性最小的 代价创建出来。不将activity运行起来,没有数据存储和交互依赖关系。
Android测试:类的结构 java.lang.Object junit.framework.Assert junit.framework.TestCase android.test.InstrumentationTestCase android.test.AndroidTestCase android.test.ApplicationTestCase<T extends android.app.Application> android.test.LoaderTestCase
android.test.ProviderTestCase2<T extends android.content.ContentPrivider> android.test.ServiceTestCase<T extends android.app.Service> android.test.ActivityTestCase android.test.ActivityInstrumentationTestCase2<T extends android.app.Activity> android.test.ProviderTestCase<T extends android.content.ContentProvider> android.test.ActivityUnitTestCase<T extends android.app.Activity> android.test.SingleLaunchActivityTestCase<T extends android.app.Activity>
Android测试:实例
谢谢!