软件工程导论全ppt课件.ppt
面向对象实现,程序设计语言 程序设计风格 测试策略 设计测试用例,一、程序设计语言,1、面向对象语言的优点 一致的表示方法 (2)可重用性 (3)可维护性,2、面向对象语言的技术特点 (1)支持类与对象概念的机制 (2)实现整体-部分结构的机制 (3)实现一般-特殊结构的机制 (4)实现属性和服务机制 (5)类型检查 (6)类库 (7)效率 (8)持久保存对象 (9)参数化类 (10)开发环境,3、选择面向对象语言 (1)将来能否占主导地位 (2)可重用性 (3)类库和开发环境 (4)其他因素,二 程序设计风格,提高可重用性提高可扩充性提高健壮性,三 面向对象的软件测试,测试目标:在现实的时间跨度内应用可管理 的工作量去发现最大可能数量的 错误,基本目标不变,但由于OO程序的性质改变了测试策略 和测试战术更多的设计模式复用是否将减轻OO系统的繁重测试?Binder,R.V.在“Object-Oriented Software Testing”中讨论改问题:“每次复用是一个新的使用语境,并且重新测试是谨慎的.为了获得面向对象系统的高可靠性,似乎可能需要更多而不是更少的测试.”,1 OOA和OOD的 模型测试,每个阶段的所有面向对象模型都应被测试。 OOA和OOD的模型不能被执行,对它们不能进行传统意义上的测试。,可通过技术复审检查OOA和OOD的模型的正确性和一致性。,扩大测试的视角,2 面向对象测试策略,信息隐蔽对测试的影响封装和继承对测试的影响,面向对象程序的特点对软件测试的影响:,单元和集成测试策略必须有很大的改变测试用例的设计必须考虑OO软件的特征,(1). OO的单元测试,一个类可以包含一组不同的操作,而一个特定 的操作也可能存在于一组不同的类中。不再孤 立地测试单个操作(这是传统单元测试的视角)OO软件的类测试等价于传统的单元测试.传统软件的单元测试关注算法细节和模块接口 间流动的数据 OO软件的类测试是由封装在类中的操作和类的 状态行为驱动的,单元概念的变化封装的类或对象作为最小 的可测试单位,(2). OO的集成测试,OO软件没有层次的控制结构,传统的自顶向下和自底向上的集成策略没有意义.,OO软件的集成两种策略:基于线程的测试(thread-based testing) 集成响应系统的一个输入或事件所需的一组类,每个线程被个体地集成和测试,通过回归测试保证没有副作用产生;基于使用的测试(use-based testing) 通过测试几乎不使用服务器的类(独立类)来开始系统的构造,测试完独立类后,使用独立类按层逐步完成依赖类的测试直至完整的系统被构造;,(3). OO的确认测试,在确认和系统测试层次,类连接的细节消失.,和传统的确认测试一样,OO软件的确认关注 用户可见的动作和用户可识别的系统输出.为辅助确认测试的导出, 应利用分析模型中的 用例图提供的场景来提高交互需求中发现错误 的可能性,3 OO软件的测试用例设计,每个测试用例应被唯一标识,并应显式地和与被 测试类相关联测试的目的应被陈述对每个测试应开发一组测试步骤,包括:将被测试对象的一组特定状态将被作为测试的结果使用的一组消息和操作当对象被测试时可能产生的一组异常一组外部条件(进行测试必须的软件外部环境的变化)将辅助理解或实现测试的补充信息,OO软件的测试用例设计还处于成型期.Binder,R.V.在“Essays on Object-Oriented Software Engineering”中建议了对OO软件的测试用例设计的整体方法:,(1). OO概念的测试用例设计的含义,封装可能会成为测试的障碍 测试需要报告对象的具体和抽象状态,而封装 使得对象的状态快照难于获得。继承,特别是多继承使测试复杂化,子类继承或重载的父类成员函数的测试问题,继承的成员函数是否都不需要测试? 对父类中已经测试过的成员函数,两种情况需要 在子类中重新测试: 继承的成员函数在子类中做了改动; 成员函数调用了改动过的成员函数的部分;例如: 父类Base有两个成员函数Inherited()和Redefined(), 子类Derived只对Redefined() 做了改动. Derived Redefined() 需要重新测试 Derived Inherited() 如果它调用了Redefined() 的 语句,则需重新测试,否则不必,子类继承或重载的父类成员函数的测试问题,对父类的测试是否能够照搬到子类? 上例中: BaseRedefined() 和Derived Redefined() 已是两个不同的成员函数, 照理应对Derived Redefined() 重新进行测试分析, 设计测试用例,但由于它们的相似性,只需在BaseRedefined() 的测试要求和测试用例上添加对Derived Redefined() 的新的测试要求和增补相应的测试用例.,(2). 传统测试用例设计方法的可用性,白盒测试方法可用于类定义的操作的测试对具有简洁结构的类,白盒测试最好用于类级别 的测试黑盒测试方法也适合OO系统,4 测试单个类的方法,(1)随机测试,例:银行系统的account(帐户)类有下列操作:open(打开)setup(建立)deposit(存款)withdraw(取款)balance(余额)summarize(清单)creditLimit(透支限额)close(关闭)系统对操作的限制:必须在应用其它操作之前先打开帐户,在完成了 全部操作之后才能关闭帐户;,在限制下还是存在操作的许多排列,一个account类实例的最小行为历史包括下列操作:open . setup . deposit . withdraw . close account类的最小测试序列大量的其它行为可能在下面序列中发生:open . setup . deposit . deposit | withdraw | balance | summarize | creditLimit n . withdraw . close 一系列不同的操作序列可以随机地产生,例如:测试用例r1: open.setup.deposit.deposit.balance. summarize.creditLimit.withdraw.close 测试用例r2: open.setup.deposit.withdraw.deposit. balance. creditLimit.withdraw.close这些和其它的随机顺序测试被进行,以测试不同的类实例的生存历史.,测试单个类的方法,(2)划分测试(partition testing) 与测试传统软件时采用的等价类划分方法类似. 划分类别的方法:基于状态的划分基于属性的划分基于功能的划分,基于状态的划分,根据类操作改变类状态的能力来划分类操作.,例:银行系统的account(帐户)类 状态操作包括: deposit(存款) withdraw(取款) 非状态操作包括:balance(余额) summarize(清单) creditLimit(透支限额)测试用例p1(测试改变状态的操作): open.setup.deposit.deposit.withdraw.close 测试用例p2 (测试不改变状态的操作,在最小测试序列中 的操作除外) : open.setup.deposit.summarize. creditLimit.withdraw.close,基于属性的划分,根据类操作使用的属性来划分类操作.,例:银行系统的account(帐户)类可根据balance属 性来定义划分,把操作划分为三个类别: 使用balance的操作 修改balance的操作 不使用也不修改balance的操作 为上述每个类别设计测试序列,基于功能的划分,根据类操作所完成的功能来划分类操作.,例:银行系统的account(帐户)类中的操作可划分 为三个类别: 初始化操作(open, setup) 计算操作(deposit, withdraw) 查询操作(balance, summarize, creditLimit) 终止操作(close) 为上述每个类别设计测试序列,测试类和方法,(3)基于故障的测试(fault_based testing),与测试传统软件时采用的错误推测法类似.,5 面向对象的集成测试 (类间测试用例的设计),在OO系统的集成开始时, 开始类间的协作测试. 和单个类的测试一样, 类协作测试可通过随机和划分方法以及基于场景的测试和行为测试来完成.,ATM,Bank,银行系统的类协作图,ATMUserInterface,Account,Cashier,verifyAcctverifyPINverifyPolicywithdrawReqdepositReqacctInfoReq,cardInsertedpassworddepositwithdrawaccentStatusterminate,validPINvalidAcct,creditLimitaccentTypebalancewithdrawdepositclose,openAcctinitialDepositauthorizeCarddeuthorizecloseAcct,ValidationInfo,verifyStatusdepositStatusdispenseCaseprintAccentStatreadCardInfogetCaseAmnt,OO集成测试方法,(1)多个类测试 Kirani,S.and W.T.Tsai,在“Specification and Verification of Object-Oriented Programs” 中建议了下面的步骤序列以生成多个类随机测试用例:1.对每个客户类,使用类操作列表来生成一系列随机测试序列,这些操作发送消息给服务器类;2.对生成的每个消息,确定在服务器对象中的协作者类和对应的操作;3.对服务器对象中的每个操作(已经被来自客户对象的消息调用),确定传递的消息;4.对每个消息,确定下一层被调用的操作,并把这些操作结合进测试序列中.,ATM,Bank,银行系统的类协作图,ATMUserInterface,Account,Cashier,verifyAcctverifyPINverifyPolicywithdrawReqdepositReqacctInfoReq,cardInsertedpassworddepositwithdrawaccentStatusterminate,validPINvalidAcct,creditLimitaccentTypebalancewithdrawdepositclose,openAcctinitialDepositauthorizeCarddeuthorizecloseAcct,ValidationInfo,verifyStatusdepositStatusdispenseCaseprintAccentStatreadCardInfogetCaseAmnt,银行系统中Bank类和ATM类的操作序列:,verifyAcct verifyPIN verifyPolicy withdrawReq | depositReq | acctInfoReqn对Bank类的随机测试用例可能是:测试用例r3: verifyAcct verifyPIN depositReq,为了考虑测试中涉及的协作者,需要考虑与测试用例r3中每个操作相关联的消息:Bank必须和ValidationInfo协作以执行verifyAcct和verifyPINBank还必须和Account协作以执行depositReq因此,测试这些协作的新的测试用例是: 测试用例r4:verifyAcctBank validAcctValidationInfo verifyPINBank validPINValidationInfo depositReq depositAccount,OO集成测试方法,(2)从动态模型导出测试用例 设计的测试用例应达到完全的状态覆盖,即操作序列应导致account类的变迁穿越所有允许的状态:测试用例s1: opensetupAccent deposit(initial) withdraw(final) close(最小测试序列),向最小序列中加入附加的测试序列,例如:测试用例s2:opensetupAccent deposit(initial) deposit balance credit withdraw(final) close测试用例s3:opensetupAccent deposit(initial) deposit withdraw accntInfo withdraw(final) close 导出更多的测试用例以保证该类的所有行为都被适当地测试,set upacct,account类的状态转换图,emptyacct,deadacct,setup Aaccent,balance creditacctInfo,close,deposit(initial),deposit,withdraw,emptyacct,open,withdrawal(final),nonworkingacct,