面向对象的软件单元测试概述_第1页
面向对象的软件单元测试概述_第2页
面向对象的软件单元测试概述_第3页
面向对象的软件单元测试概述_第4页
面向对象的软件单元测试概述_第5页
已阅读5页,还剩32页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、技术创新,变革未来面向对象的软件单元测试概述面向对象的基本概念对象类消息接口封装继承多态面向对象的基本概念Peter Coad 和 Edward Yourdon 提出下列等式认识面向对象方法: 面向对象 对象(Object) 分类(Classification) 继承(Inheritance) 通过消息的通信 (Communication with message)采用这四个概念开发的软件系统是面向对象的。面向对象技术面向对象方法的出现,实际上是程序设计方法发展的-个返朴归真过程。面向对象的实质:从系统的组成上来进行分解。对问题自然分割,利用类及对象作为基本构造单元,以更接近人类思维的方式建立

2、问题域模型,从而使设计出的软件尽可能直接地描述现实世界,构造出模块化的、可重用的、可维护性好的软件,并能控制软件的复杂性降低开发维护费用。对象对象是指包含了一组属性以及对这些属性的操作的封装体。对象之间存在着一定的关系,对象之间的交互与合作构成更高级的行为。王五由他的头、胳膊、腿和身体组成汽车是一种交通工具对象间的由分解所构成的关系,part of层次;具有代表一种一般特性的对象之间的聚合关系,is a层次;代表更一般的对象间在物理上或概念上有关的相关关系。人乘坐或驾驶汽车对象是软件开发期间测试的直接目标。面向对象软件测试所关注的焦点: (1)对象的行为是否符合它的规定说明; (2)该对象与和

3、它相关的对象是否协同工作。面向对象的单元测试面向对象测试的单元定义可以编译执行的最小软件组件;(和传统测试一样,但放弃了封装的特点)由一个设计人员开发的软件组件;只包含单一操作或方法的类或子类。(设计用例方便,使集成测试目标清晰)以方法为单元还是以类为单元,根据具体环境确定最适合的方法。“操作”是指类函数定义,“方法”指其实现。面向对象的单元测试-以方法为单元传统的单元测试是针对程序的函数、过程或完成某一特定功能的程序块。单独的看待类的成员函数,与面向过程程序中的函数或过程没有本质的区别,传统的测试方法在面向对象单元测试中都可使用,如等价类划分法、因果图法、边值分析法、逻辑覆盖法、路径分析法等

4、等。面向对象编程的特性使得对成员函数的测试又不完全等同于传统的函数或过程测试。不再孤立地测试单个操作,而是将操作作为类的一部分。尤其是继承特性和多态特性,使子类继承或重载的父类成员函数出现了传统测试中未遇见的问题。考虑如下两个问题:(1)继承的成员函数是否都不需要测试?(2)对父类的测试是否能照搬到子类?面向对象的单元测试(续)继承的成员函数是否都不需要测试? 对父类中已经测试过的成员函数,以下两种情况需要在子类中重新测试: a)继承的成员函数在子类中做了改动; b)成员函数调用了改动过的成员函数的部分。例:假设存在父类Base有Inherited()和Redefined()这两个成员函数,继

5、承父类Base的子类Derived只对Redefined() 做了改动。那么,Derived:Redefined()就需要重新测试;对于Derived:Inherited(),若它包含了调用Redefined()的语句 (比如:x=x/Redefined()),就需要重新测试,否则就不需要。面向对象的单元测试(续)对父类的测试是否能照搬到子类? 引用前面的假设,成员函数Base:Redefined()和Derived:Redefined()已经是不同的。那么,按理应该要对Derived:Redefined()重新测试分析,设计测试用例。但是由于面向对象的继承使得两个函数相似,故只需要在对Bas

6、e:Redefined()的测试要求和测试用例上添加对Derived:Redefined()新的测试要求和增补相应测试用例。例 Base:Redefined()含有如下语句: If (value0) message(“less”); else if (value=0) message(“equal”); else message(“more”); 面向对象的单元测试(续)例(续) 在Derived:Redefined()中定义为: If (value0) message(“less”); else if (value=0) message(“It is equal”); else messag

7、e(“more”); if (value=88) message(“luck”); 在原有对父类Base的测试上,对Derived:Redefined()的测试只需作如下改动:将value=0的测试结果期望改动;增加value=88的测试。 设计测试用例需要能够实例化的“桩”类和起驱动器作用的“主程序”类;方法一般比较简单,复杂度较低;创建桩工作量较大;测试工作主要集中在集成测试:类内和类间; 例:o-oCalendar的伪代码:CalendarUnit类:两个操作(设置取值和标志)Testlt类(测试驱动器)Date类(获取日期,计算下一日期并打印日期)Day类(设置/获取日期)Month

8、类(设置/获取月份及天数)Year类(设置/获取年份及闰年判别)Testlt类和Date类123testIt4567Date.constructor891011121314151617181920Date.incrementDate.printDateDay类212223Day.constructorabDay.setCurrentPos232425Day.setDay2627Day.getDay282930313233Day.increment394041Month.constructorabMonth.setCurrentPos363738Month.setMonth3940Month.g

9、etMonth474849505152Month.increment414246434445Month.getMonthSizeMonth类的程序图类:CalendarUnit class CalendarUnit abstract class currentPos As Integer CalendarUnit(pCurrnetPos) currentPos = pCurrnetPos End CalendarUnita. setCurrentPos(pCurrnetPos)b. currentPos = pCurrnetPos End setCurrentPos abstract prot

10、ected boolean increment()类:testlt class testlt main()1. Date testdate(testMonth,testDay,testYear)2. testdate.increment()3. testdate.printDate() End testlt类:Date class Date private Day d private Month m private Year y4. Date(pMonth,pDay,pYear)5. Year y(pYear)6. Month m(pMonth,y)7. Day d(pDay,m) End D

11、ate constructor19.printDate()20. Output(m.getMonth()+”/”+d.getDay()+”/”+y.getYear() End printDate8. increment()9. if (NOT(d.increment()10.Then11. if(NOT(m.increment()12. Then13. y.increment()14. m.setMonth(1,y) d.setDay(1,m)15. Else16. d.setDay(1,m)17. Endif18.Endif End increment类:Day class Day is A

12、 CalendarUnit private Month m21. Day(pDay,Month pMonth)22. setDay(pDay,pMonth) End Day constructor23. setDay(pDay, pMonth)24. setCurrentPos(pDay)25. m = pMonth End setDay26. getDay()27. return currentPos End getDay28. boolean increment()29. currentPos = currentPos+130. if(currentPos=m.getMonthSize()

13、31. Then return true32. Else return false33. Endif End increment类:Month class Month is A CalendarUnit private Year y private sizeIndex=34.Month(pcur,Year pYear)35. setMonth(pcur,Year pYear) End Month constructor36.setMonth(pcur,Year pYear)37. setCurrentPos(pcur)38. y=pYear End setMonth39.getMonth()4

14、0. return currentPos End getMonth41.getMonthSize()42. if(y.isleap()43. Then sizeIndex1=2944. Else sizeIndex1=2845. Endif46. return sizeIndexcurrentPos-1 End getMonthSize47.boolean increment()48. currentPos=currentPos+149. if(currentPos12)50. Then return fasle51. Else return true52. Endif End increme

15、nt类:Year class Year is A CalendarUnit53. Year(pYear)54. setCurrentPos(pYear) End Year constructor55. getYear()56. return currentPos End getYear57. boolean increment()58. currentPos = currentPos+159. return true End increment60. boolean isleap()61. if(currentPos MOD 4=0)AND NOT(currentPos MOD 100=0)O

16、R(currentPos MOD 400=0)62. Then return true63. Else return false64. Endif End isleapDate.increment的单元测试三个等价类:D1=日期:1=日期月的最后日期D2=日期:日期是非12月的最后日期D3=日期:日期是12月31日 可以解决类内集成问题;主要问题是类的继承性、抽象类等问题;静态视图继承被忽略,扁平化的类可以解决;不能测试抽象类;以类为单元在没有类的继承性,只有内部的复杂性时最有意义面向对象的单元测试-以类为单元类的功能性和结构性测试对面向对象软件的类测试相当于传统软件中的单元测试。 类的测试用

17、例可以先根据其中的方法设计,然后扩展到方法之间的调用关系。类测试一般也采用传统的两种测试方式:功能性测试和结构性测试,即黑盒测试和白盒测试。功能性测试以类的规格说明为基础,主要检查类是否符合其规格说明的要求。功能性测试包括两个层次:类的规格说明和方法的规格说明。结构性测试则是从程序出发,对类中方法进行测试,需要考虑其中的代码是否正确。测试分为两层:第一层考虑类中各独立方法的代码,即方法要做单独测试;第二层考虑方法之间的相互作用,即方法需要进行综合测试。例:挡风玻璃雨刷(三个类合并为一个类)class windshieldWiper private wiperSpeed;leverPositio

18、n;dialPosition windshieldWiper(wiperSpeed,leverPosition,dialPosition) getWiperSpeed() setWiperSpeed() getLeverPosition() setLeverPosition() getDialPosition() setDialPosition() senseLeverUp() senseLeverDown() senseDialUp() senseDialDown()End class windshieldWiper断电加电关间歇低速高速123046123060leverdownleveru

19、pleverdownleverdownleverupleverupdialDowndialDowndialUpdialUpInstate(Int)Instate(off)Instate(1)Instate(2)Instate(3)Instate(low)Instate(High)Instate(Int)Instate(low)Instate(1)Instate(2)windshieldWiper类的状态图senseLeverUp() Case leverPosition Of Case 1:Off leverPosition=Int Case dialPosition Of Case 1:1

20、wiperSpeed=4 Case 2:2 wiperSpeed=6 Case 3:3 wiperSpeed=12 EndCase dialPosition Case 2:Int leverPosition=Low wiperSpeed=30 Case 3:Low leverPosition=High wiperSpeed=60 Case 4:High (impossible;error condition) EndCase leverPosition windshieldWiper类的单元测试采用由下往上的测试;senseLeverUp/ senseLeverDown/DialUp/Dial

21、Down的测试测试windshieldWiper类的其他部分测试驱动器类的伪代码:class testSenseLeverUp wiperSpeed leverPos dialPos testResult booleanmain() windshieldWiper testCase(0,Off,1) testCase.senseLeverUp() leverPos= testCase.getLeverPosition() if leverPos=Int Then testResult=Pass Else testResult=Fail EndifEnd mainclass testWindsh

22、ieldWiper wiperSpeed leverPos dialPos testResult booleanmain() windshieldWiper testCase(0,Off,1) testCase.senseLeverUp() wiperSpeed = testCase.getWiperSpeed() if wiperSpeed=4 Then testResult=Pass Else testResult=Fail EndifEnd main基于类行为图定义测试覆盖指标:每个事件的覆盖组件中每个状态的覆盖;组件中每个转移的覆盖;所有交互状态覆盖;客户定义用例场景;测试用例前提wi

23、ndshieldWiper事件(方法)预期leverPos的输出值123456windshieldWiper(0,Off,1)windshieldWiper(0,Int,1) windshieldWiper(0,Low,1)windshieldWiper(0,High,1)windshieldWiper(0,Low,1)windshieldWiper(0,Int,1)senseLeverUp()senseLeverUp()senseLeverUp()senseLeverDown()senseLeverDown()senseLeverDown()“间歇”“低速”“高速”“低速”“间歇”“关”控制

24、杆组件每个状态/转移覆盖层次的测试用例:场景覆盖准则与系统级测试几乎相同,场景:UC1正常用法描述前提挡风玻璃雨刷在“关”位置,“刻度盘”在位置1;用户将控制杆推到“间歇”,然后将刻度盘从位置2转到位置3;然后将控制杆推到“低速”;用户将控制杆推到“间歇”,然后推到“关”挡风玻璃雨刷在“关”位置,“刻度盘”在位置1,雨刷速度为0事件序列用户行动系统应答123456将控制杆推到“间歇”将刻度盘转到2将刻度盘转到3将控制杆推到“低速”将控制杆推到“间歇”将控制杆推到“关”雨刷速度为4雨刷速度为6雨刷速度为12雨刷速度为30雨刷速度为12雨刷速度为0测试用例:class testScenario wiperSpeed leverPos dialPos step1OK boolean step2OK boolean step3OK boolean step4OK boolean step5OK boolean

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论