




免费预览已结束,剩余72页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
单元测试,第五讲,主要内容,单元测试介绍单元测试QuickStart使用JUNIT测试的一些技巧边界条件MOCK对象简介单元测试与软件设计,1.单元测试介绍,1.1什么是单元测试,单元测试是开发者写的一小段代码,用于检验被测代码的一个很小的、明确的功能是否正确。通常而言,一个单元测试是用于判断某个特定条件下某个特定的函数的行为。执行单元测试,是为了证明某段代码的行为确定和开发者所期望的一致。,1.2单元测试的目的,及早发现软件开发过程中实现或者设计带来的缺陷跟踪详细设计文档中设计的实现,发现详细设计文档中存在的错误验证单元代码和详细设计文档的一致性发现在编码过程中引入的错误,单元测试标准是什么,单元测试标准通常为详细设计说明书但是在没有详细设计说明书的情况下可以以注释为测试标准,单元测试过程,单元测试计划单元测试设计单元测试实现单元测试执行单元测试评估,单元测试计划,时间表工作量任务分配资源安排测试工具结束标准风险分析风险应对输出单元测试计划文档,单元测试设计,对哪些单元进行测试被测单元的关系被测单元与其他模块的关系测试策略选择如何设计测试用例如何设计单元测试代码输出单元测试用例文档,单元测试实现,编写测试用例编写测试规程测试脚本编写测试驱动构建桩构建输出测试用例输出测试规程输出测试代码和脚本,单元测试执行,搭建测试环境执行测试脚本记录测试结果跟踪缺陷回归测试输出单元测试报告,单元测试策略,自顶向下的单元测试方法先对最顶层的单元进行测试,把顶层单元所调用的单元做成桩模块。其次对第二层单元进行测试,使用上面已测试的单元做驱动模块。依次类推直至测试完所有的模块。优点可以节省驱动函数开发的工作量,测试效率较高缺点随着被测单元一个个的加入,测试过程将变得复杂,并且开发和维护的成本将增加。自底向上的单元测试孤立的单元测试混合的单元测试,自底向上的单元测试先对最底层的单元进行测试,模拟主调单元构建驱动模块。然后再对上面一层做单元测试,用下面已经测试通过的模块做桩模块。依次类推,直至测试完所有的模块。优点可以节省桩模块开发的工作量,测试效率高缺点不是纯粹的单元测试,底层函数的测试质量对上层函数的测试将产生很大的影响。,孤立的单元测试方法不考虑模块和模块之间的关系,为每个模块设立桩模块和驱动模块。每个模块进行独立的单元测试优点该策略最简单,最容易操作。可以达到很高的覆盖率。似乎纯粹的单元测试缺点该策略效率很低,需要构建大量的驱动和桩,混合的单元测试自顶向下和自底向上的测试策略综合了集成的概念,随着单元测试的进行,可以看到系统一个初步集成的概貌,但是测试覆盖率会越来越难保证。并且在每个单元测试之前必须保证相关的单元的正确性。孤立的测试策略比较独立,覆盖率容易保证,并且可以并行进行,但工作量大。所以采用混合方法比较好。,单元测试用例设计,单元测试用例设计方法黑盒白盒单元测试用例编写思路为系统运行起来设计测试用例为正向测试设计用例为逆向测试设计用例为满足特殊需求而设计用例为代码覆盖而设计测试用例,单元测试用例设计五要点单元接口局部数据结构独立路径出错处理边界条件,理解需求和设计设计测试用例搭建单元测试环境执行测试补充和完善测试用例分析结果,给出评价,1.3我需要做什么呢,它的行为和我的期望一致吗?它的行为一直和我的期望一致吗?我可以依赖单元测试吗?单元测试说明我的意图了吗?,1.4不写单元测试的借口,编写单元测试太花时间了运行测试的时间太长了测试代码并不是我的工作我并不清楚代码的行为,所以也就无从测试但是这些代码都能编译通过公司请我是为了写代码,而不是写单元测试如果我让测试员失去工作,我会觉得内疚公司不会让我在真实系统中运行单元测试,2.单元测试QuickStart,2.1测试对象,寻找数组中的最大数:publicclassLargestpublicstaticintlargest(intlist)intindex,max=Integer.MAX_VALUE;for(index=0;indexmax)max=listindex;returnmax;,2.2设计测试,排序测试:【9,7,8】9【7,9,8】9【7,8,9】9重复值:【7,9,8,9】9单值:【1】1负值:【-9,-8,-7】-7.空值,2.3执行测试,执行测试并修正错误理解单元测试,3.使用JUNIT,Junit简介,Junit的定位,Junit的安装,Junit的体系结构,Junit的使用,3.1构建单元测试,TestAccount.javaAccount.java准备要测试的条件调用要测试的方法验证被测试方法的行为是否和结果一致完成后清理各种资源,testCreateAccount()testCreateAccountDef()testCreateAccountDup(),createAccount(),3.2JUNIT的各种断言,assertEquals(Stringmessage,expected,actual)assertEquals(Stringmessage,expected,actual,tolerance)assertNull(Stringmessage,Objectobject)assertNotNull(Stringmessage,Objectobject)assertSame(Stringmessage,expected,actual)assertNotSame(Stringmessage,expected,actual)assertTrue(Stringmessage,booleancondition)assertFalse(Stringmessage,booleancondition)fail(Stringmessage)自定义断言,3.3JUNIT框架,importjunit.framework.*;/引入测试包publicclassTestSimpleextendsTestCase/继承TestCasepublicTestSimple(Stringname)/默认使用父类的实例化方法super(name);publicvoidtestAdd()/书写以test开头的断言,凡是以test开头的都会/被junit自动运行assertEquals(2,1+1);publicvoidtestAdds()/一个测试方法里也可以有多个断言assertEquals(2,1+1);assertEquals(4,2+2);assertEquals(-8,-12+4);,测试类也能调用其他测试类:单独的类、包、甚至完整的一个系统。这可以通过创建testsuite来取得。任何测试类都能包含一个名为suite的静态方法:PublicstaticTestsuite();现假设有第2个类TestClassTwo,它使用brute-force算法来寻找旅行销售商Bob的最短行程。但这个算法是复杂度是指数级的。默认情况下你不想包括这些测试。,3.4JUNIT测试的组成(1),importjunit.framework.*;publicclassTestClassTwoextendsTestCasepublicTestClassTwo(Stringmethod)super(method);publicvoidtestLongRunner()publicvoidtestShortTest()publicvoidtestAnotherShortTest()publicstaticTestsuite()TestSuitesuite=newTestSuite();suite.addTest(newTestClassTwo(“testShortTest”);/装入测试方法suite.addTest(newTestClassTwo(testAnotherShortTest);returnsuite;,3.4JUNIT测试的组成(2),importjunit.framework.*;publicclassTestClassCompositeextendsTestCasepublicTestClassComposite(Stringmethod)super(method);staticpublicTestsuite()TestSuitesuite=newTestSuite();/执行第一个测试类所有的测试suite.addTestSuite(TestClassOne.class);/执行第二个测试类中指定的测试suite.addTest(TestClassTwo.suite();returnsuite;,假设对于每个测试,你都需要某种数据库连接,这时,你不需要在每个测试方法中重复建立连接和释放连接了,而只须在setup和teardown方法中分别建立和释放连接。执行每个测试方法之前会执行setup,之后会执行teardown,JUnit和异常,对测试而言,下面两种异常我们可能会感兴趣:从测试代码抛出的可预测异常。由于某个某块(或代码)发生严重错误,而抛出的不可预测异常。如有一个名为sortMyList()的方法,如果传入参数是一个nulllist,那么我们希望该方法抛出一个异常。在这种情况下,我们就需要显式地测试这一点。,assertTure(true)表示“我预期控制流程会达到这个地方。Junit可以捕获任何异常,并且把它报告为一个错误,这些都不需要你的参与。更好的是,Junit不只是让一个断言失败,而是能够跟踪整个堆栈,并且报告bug的堆栈调用顺序,当你需要查找一个失败测试的原因时,这将非常有用。,4.测试哪些内容,4.1测试内容(Right-BICEP),Right-结果是否正确?B-是否所有的边界条件都是正确的?I-能查一下反向关联吗?C-能使用其它手段交叉检查一下结果吗?E-你是否可以强制错误条件发生?P-是否满足性能要求?,完全伪造或者不一致的输入数据,例如一个名为“!*w:gjagja;,/.d;”的文件。格式错误的数据,例如没有顶层域名的电子邮件地址,如fredfoobar空值或不完整的值一些与意料中的合理值相去甚远的数值。如一个岁数为10000岁。如果要求的是一个不允许出现重复数值的list,但是传入的是一个存在重复数值的list如果要求的是一个有序list,但是传入的是一个无序list;或者反之事情到达的次序是错误的,或者碰巧和期望的次序不一致,如未登陆系统之前,就尝试打印文档。,可能的边界值,反向关联,如对结果进行平方的方式来检查一个计算平方根的函数,然后测试结果是否和原数据很接近。类似地,为了检查某条记录是否成功地插入了数据库,你也可以通过查询这条记录来验证。,其它手段交叉检查,通常计算一个量会有一种以上的算法。我们可能会基于运行效率或者其他的特性,来选择算法,那是我们要在产品中使用的,但在测试时可以使用剩下的算法来做交叉测试。,其它手段交叉检查,另一种办法,使用类本身不同组成部分的数据,并且确信它们能“合起来”。如,正在做一个图书馆的数据系统。在这个系统中,对每一本具体的书,它的数量永远是平衡的。我们可以用一种数量检查另一种数量。,强制产生错误条件,真实世界中,错误总是会发生:磁盘会满,网络连线会断开,电子邮件会多得像掉进了黑洞,而程序会崩溃。你应当能够通过强制引发错误,来测试你的代码是如何处理所有这些真实世界中的问题的。,强制产生错误条件,性能问题,不是性能本身如:“随着输入尺寸慢慢变大,问题慢慢变复杂”的趋势。确保性能曲线能够保持稳定,5.CORRECT边界条件,5.1边界条件,思考publicintcalculate(inta,intb)returna/(a+b);,5.2边界条件,一致性(Conformance)值是否和预期的一致有序性(Ordering)值是否如应该的那样,是有序或无序区间性(Range)值是否位于合理的最小值和最大值之内。引用,耦合性(Reference)代码是否引用了一些不在代码本身控制范围之内的外部资源,5.2边界条件,存在性(Existence):值是否存在基数性(Cardinality)是否恰好有足够的值时间性(Time),区间性,如果数据不能像你期望的那样与结构相一致,将会出现什么情况?象这种情况,你就需要测试你的结果并确保其一致性。(一致性)任何一个搜索程序都应该针对搜索目标位于最前或最后的条件做测试。(有序性)如果这种情况可能发生,并且在发生的时候,你的程序需要处理她,那么你就需要测试这种情况。,耦合性,如,网站上一个用来显示用户记录的方法,可能要求用户先登录。栈的pop()方法要求一个非空的栈。给汽车换挡。前条件、后条件,存在性,通过询问:“给定的事物存在吗?”对于你传入或者维护的值,先询问如果值不存在如果它为null、或者等于0,方法的行为将会怎样?面对这些不存在的数据,java库的许多方法会抛出异常。然而要调试一个隐藏在库深处的运行期异常通常并不容易。在期望值不存在的时候,大多数方法都会失败,但这可能并不是你所期望的结果。因此,你可以对这些情况进行测试,查看当网络不通、文件不存在的时候,又会发生什么事情。确认你的方法处理了“不存在”的情况。,一年中的每一天都是24小时吗?并发问题,练习(思考栈的测试方法),publicinterfaceStackExercisepublicStringpop()throwsStackEmptyException;publicvoidpush(Stringitem);publicStringtop()throwsStackEmptyException;publicbooleanisEmpty();,答案(思考栈的测试方法),对于空栈isEmpty=true,pop(),top(),抛异常。push(“字符”),top(),返回刚压入的字符串,isEmpty()=false。多次调用push();验证每一次top()。push(null),top()=null。发生异常后,栈仍可以使用。,6.MOCK对象简介,6.1MOCK对象,概念:MOCK对象是真实对象在调试期间的替代品。,简单的替换,一般,我们建议对应用程序范围外的功能调用进行包装。因为被测试代码只会通过接口来引用对象,所以它完全不知道它引用的究竟是真实对象还是mock对象。,在产品环境(卖给客户的真正的代码)中,当初始化这个类的对象时,传入的是一个真实的systemEnvironment,而另一方面,测试代码传入的是则是mockSystemEnvironment。,6.2什么情况下使用MOCK对象,真实对象行为不确定(如股票行情)。真实对象很难被创建。真实对象的某些行为很难被触发。真实对象令程序的运行很慢。真实对象有(或者是)用户界面。测试含有回调函数。真实对象并不存在。,6.3使用MOCK对象的步骤,使用一个接口来描述这个对象。为产品代码实现这个接口。以测试为目的,在MOCK对象中实现这个接口。,练习:实现MP3的MOCK对象,importjava.util.ArrayList;publicinterfaceMp3Playerpublicvoidplay();publicvoidpause();publicvoidstop();publicdoublecurrentPosition();publicStringcurrentSong();publicvoidnext();publicvoidprev();publicbooleanisPlaying();publicvoidloadSongs(ArrayListnames);,7.单元测试与软件设计,7.1软件设计关注的几个层面,通过面向测试的软件设计,更好地分离关注点。通过测试驱动的方法,改善接口设计。确立和局部化验证的责任。,7.2面向测试的软件设计,例:publicvoidsleepUtilNextHourthrowsInterrupedExceptioninthowlong;计算休眠时间的一系列代码Thread.sleep(howlong);Return;等一个小时?设一个计时器,调用这个函数,等结束后回来再检查时间,如果失败了,再来处理一下,重新测试?,7.3面向测试的软件设计,重构代码publicvoidsleepUtilNextHourthrowsInterrupedExceptioninthowlong=milliSecondsTONextHour(newDate();Thread.sleep(howlong);Return;测试:asserEquals(10000,milliSecondsTONextHour(TEST_DAY_10));如果测试代码非常丑陋或难写,暗示软件设计需要调整。,7.5测试驱动开发(一),例如:一个把标准纸张规格输出的方法addCorpMarks(PPstreamstr,intpaper_width,intpaper_height,intbody_width,intbody_h
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 城市轨道交通市域线行车组织优化
- 萜烯合成酶基因Os03g22634在水稻抗病虫害中的功能分析
- 文本细读在统编版高中文言议论文教学中的应用-以南疆K市中学为例
- 党校考试试题及答案期末
- 潇湘职业学院《制药设备》2023-2024学年第二学期期末试卷
- 中国民航大学《电视新闻学》2023-2024学年第二学期期末试卷
- 陕西工商职业学院《社区康复医学》2023-2024学年第二学期期末试卷
- 韩国面小店企业制定与实施新质生产力项目商业计划书
- 可回收材料艺术创作行业深度调研及发展项目商业计划书
- 天津市河西区2024-2025学年高一上学期期末质量调查数学试题(解析版)
- 8-马工程《艺术学概论》课件-第八章(2019.4.2)【已改格式】.课件电子教案
- 人教版七年级下册英语单词辨音训练题(一)
- 公共政策的经济学分析课件
- 与总包等的协调配合措施
- 新世纪健康饮食课件
- 在深化纠正“四风”和提高工作效率专题研讨会上的发言
- 道德与法治四年级(下)第二单元单元备课
- 小学音乐 花城版 二年级《稻草里的火鸡》课件
- 物质安全数据表(MSDS)84消毒液
- “363生态课堂”模式及流程
- (高清版)建筑工程风洞试验方法标准JGJ_T 338-2014
评论
0/150
提交评论