作者:致力于流浪动物救助量 | 来源:互联网 | 2023-05-31 22:15
软件测试的工作流程 一、作为测试人员需要学习并了解业务,分析需求点 为什么测试人员需要参加需求分析?也就是进行测试需求分析的目的是什么?
把用户需求转化为功能需求:1)对测试范围进行度量 2)对处理分支进行度量 3)对需求业务的场景进行度量 4)明确其功能对应的输入、处理和输出 5)把隐式需求转变为明确 明确测试活动的五个要素:测试需求是什么、决定怎么测试、明确测试时间、确定测试人员、确定测试环境:测试中需要的技能、工具以及相应的背景知识、测试过程中可能遇到的风险等等。测试需求需要做到尽可能的详细明确,以避免测试遗漏和误解。 怎么进行测试需求分析?
确定功能(业务功能、辅助功能、数据约束、易用性需求、编辑约束、参数需求、权限需求、性能约束): 1)业务功能:与用户实际业务相关功能或者细节 2)辅助功能:辅助完成业务功能的一些功能或者细节,例如:设置过滤条件 3)数据约束:功能的细节,主要是用于控制在执行功能时,数据的显示范围,数据之间的关系等 4)易用性需求:功能的细节,产品中必须提供,便于功能操作使用的一些细节,例如:快捷键等 5)编辑约束:功能的细节,在功能执行时,对输入数据项目的一些约束条件,例如只能输入数字等 6)参数需求:功能的细节,在功能执行时,需要根据参数设置不同,进行不同处理的细节 7)权限需求:功能的细节,在功能执行的过程中,根据不同的权限进行不同的处理,不包括直接限制某个功能的权限 8)性能约束:功能的细节,执行功能时,必须满足的性能需求 场景分析 1)考虑场景的调用者:考虑每一个场景提供的服务是供哪些外部模块或者系统调用的,找出所有的调用者。调用前提,约束都要考虑。每一个调用都可以考虑成一个大的业务流程(一般和外部有交互的业务出错率比较大,需要重点关注) 2)考虑系统内部各个场景之间的:形成内部业务流程,需要分析每个场景之间的约束关系,执行条件,组织出各种业务流程图 挖掘隐形需求 这需要测试工程师的经验积累:1)常用的或者规定的业务流程 2)各个业务流程分支的遍历 3)明确规定不可使用的业务流程 4)没有明确规定但是应该不可使用的业务流程 5)其他异常或者不符合规定的操作 二、测试用例设计 测试用例是测试工作的最核心模块,在执行任何测试之前,首先必须完成测试用例的编写。测试用例是指导你执行测试,帮助证明软件功能或者发现软件缺陷的一种说明。用例设计好之后进行审核。
如何进行测试用例的设计 编写测试用例之前,我们需要对项目的需求有清晰的了解,对要测试什么,按照什么顺序测试,覆盖哪些需求做到心中有数,作为测试用例的编写者不仅要了解常见的测试用例编写方法,同时需要了解被测软件的设计、功能规格说明、用户试用场景以及程序/模块的结构。 步骤 1)测试需求分析:从项目部拿到软件的需求规格说明书后,开始对项目的需求进行分析,通过自己的分析、理解,整理成为测试需求,清楚分析出被测对象具有哪些功能。明确测试用例中的测试集用例与需求的关系,即一个或多个测试用例集对应一个测试需求。 2)业务流程分析:分析完需求后,明确每一个功能的业务处理流程,不同的功能点作为业务的组合,以及项目的隐式需求。如遇到复杂的测试用例设计前,先画出软件的业务流程,从业务流程上,应得到以下信息: A. 主流程是什么? B. 条件备选流程是什么? C. 数据流向是什么? D. 关键的判断条件是什么? 3)测试用例设计 完成以上两步则可以进行测试用例设计,功能测试用例,应尽量考虑边界、异常、性能的情况,以便发现更多的隐藏问题,设计测试用例的常见方法:等价类、边界值、因果图、判定表、状态迁移、正交实验、场景法、错误推断(注意:编写测试用例时,我们尽可能取的不应该是有效等价类而应该是无效等价类) 4)编写完成之后自我检查以及部门内部评审: A. 测试用例本身的描述是否清晰,语言准确;是否存在二义性; B. 测试用例内容是否完整,是否清晰的包含输入和预期输出的结果;测试步骤是否清晰; C. 测试用例中使用的测试数据是否恰当、准确; D. 测试用例是否具有指导性,是否能灵活的指导软件测试工程师通过测试用例发现更多缺陷,而不是限制他们的思维; E. 是否考虑到测试用例执行的效率。对于不断重复执行的步骤,是否保证了验证点相同;或者测试用例的设计是否存在冗余性等。这些都可能导致测试用例执行效率低下; F. 画出软件需求跟踪矩阵,验证测试用例是否完全覆盖了需求,验证测试用例的覆盖性; G. 测试用例是否完全遵守了软件需求的规定。这一点其实有一些难做到,考虑到时间/成本的关系,应该视具体情况而定。 5)测试用例更新完善 测试用例编写完成之后要不断完善,如遇需求更改或功能新增时,测试用例必须配套修改更新,同时在测试过程中发现设计测试用例时考虑不周,需要对测试用例进行修改完善;在软件交付使用后客户反馈的软件缺陷,而缺陷又是因测试用例存在漏洞造成,也需要对测试用例进行完善。 三、测试用例执行过程 首先搭建测试环境,准备好测试数据,进行预测,预测通过之后,按照测试用例进入正式测试,有效的测试执行可以将测试用例发挥最大的价值。因此,测试用例规范执行有助于更好的发现代码中存在的缺陷,好的测试执行应该包括如下内容:
测试执行中评估测试执行时间不足,需要及时上报风险。满足质量优先,进度其次原则。 测试用例按优先级顺序执行,通常是基本、详细和异常顺序执行。 未执行用例、标志为删除或者无效的用例,需注明原因。 执行过程中有疑问的测试用例(场景、操作步骤、检查点等)需找测试设计人员澄清。 测试执行需要对用例描述的检查点逐一检查,避免遗漏。 重视不易重现的缺陷场景,可能是一个bug。 执行过程中发现有前期设计遗漏用例需要补充到用例文档并执行验证。 建议测试人员交叉执行重复测试用例,用例执行对相同测试人员有免疫性。避免可能的缺陷一直遗漏。 如果需要,建议保留测试结果,结果可视。也便于不同版本间的测试结果对比。 已确认问题需及时按照问题提单要求(规范和缺陷定级)提单。 跟踪问题单修复情况并回归验证问题单。 每轮次测试结束,find一下是否有core文件产生。(核心文件(core file),也称为核心转存(core dump),是操作系统在进程收到某些信号而终止运行时,将此时进程地址空间的内容以及有关进程状态的其他信息写出的一个磁盘文件。这种信息往往用于调试) 测试结束,将最终测试用例文档上传到归档目录,实现用例重现。 以上是针对一般的软件测试流程,如果是自动化测试的话,应该还有根据测试用例进行脚本编写,运行脚本等。 在测试用例执行过程中,包含了:功能测试阶段、缺陷跟踪阶段(bug tracking)、回归测试阶段、系统测试阶段、验收测试阶段等 (系统已满足测试条件(开发完成),按照已经评审过的测试用例依次执行,执行过程中及时记录问题,将问题及时提交到QC(Quality Control)上,要跟踪缺陷。等开发修复后进行回归测试,确认修复后关闭缺陷,如果说该问题要更新而生产上未进行验证,就把缺陷状态改为生产未验证。对有异议的缺陷经甲方、开发和测试三方进行沟通讨论,由甲方最终确定处理方式。在测试过程中也会碰到对需求有异议,会反馈给经理,由经理与甲方沟通来对该需求提出一些可行性建议,最终还是由甲方来确定具体根据各个公司的业务流程而不一样)。 三、已达准出要求的根据测试情况写测试报告,对整个测试过程和版本的质量做一个评估 测试报告是指把测试的过程和结果写成文档,对发现的问题和缺陷进行分析,为纠正软件存在的质量问题提供依据,同时为软件验收和交付打下基础。测试报告是测试阶段最后的文档产出物。优秀的测试经理或测试人员应该具备良好的文档编写能力,一份详细的测试报告包含足够的信息,包括产品质量和测试过程的评价,测试报告基于测试中的数据采集以及对最终的测试结果分析。
测试报告的内容可以总结为以下目录: 首页 引言(目的,背景,缩略语,参考文献) 测试概要(测试方法,范围,测试环境,工具) 测试结果与缺陷分析(功能,性能) 测试结论与建议(项目概况,测试时间,测试情况,结论性能汇总) 附录(缺陷统计) 至此并不算最后的完结工作,软件测试还包含了线上功能检查、当前版本问题反馈以及改进建议等。这样才算是软件测试最终结束,软件测试是贯穿于整个软件生命周期的。
用例设计方法
按照是否查看代码分类 一、白盒测试方法 逻辑覆盖测试 判定覆盖或分支覆盖遵循一些较强的逻辑覆盖准则,使每一个判断都至少有一个为真和为假的输出结果,换句话说,也就是每条分支路径都必须至少遍历一次。
判定覆盖通常可以满足语句覆盖,由于每条语句都要么是从分支语句开始,要么是从程序入口点开始的某条子路径上,如果每条分支路径都执行到了,那么每条语句也应该被执行到了。但是,仍然存在有至少三种例外情况: 程序中不存在判断 程序或子程序/方法有着多重入口点。只有从程序的特定入口点进入时,某条特定的语句才能执行到。 在ON单元(ON-unit)里的语句。遍历每条分支路径并不一定能确保所有的ON单元都能执行到。(ON单元是PL/I language中的异常处理方法,如catch块中的更现代语言。所以在执行代码的每个分支(在ON单元之外)不一定会触发所有处理的异常(在ON单元内)。) 判定覆盖要求每个判断都必须有“是”和“否”的结果,并且每条语句都至少被执行一次,而且每个入口点包括ON单元都必须至少被调用一次,判定覆盖是一种比语句覆盖更强的准则,但仍然相当不足 比判定覆盖更强一些的准则是条件覆盖。条件覆盖要求编写足够的测试用例以确保将一个判断中的每个条件的所有可能的结果至少执行一次 。补充:包括ON单元的每个入口点至少调用一次。
判定/条件覆盖准则要求设计出充足 的测试用例,将一个判断中的每个条件的所有可能的结果至少执行一次,将每个判断的所有可能结果至少执行一次,将每个入口点至少调用一次。
多重条件覆盖准则要求编写足够多的 测试用例,将每个判定中的所有可能条件结果的组合,以及所有入口都至少执行一次。
总的来说,对于包含每个判断只存在一种条件的程序,最简单的测试准测就是设计出足够数量的测试用例,实现:1)将每个判断的所有结果都至少执行一次;2)将所有的程序入口(例如入口点或ON单元)都至少调用一次,以确保全部的语句都至少执行一次。 而对于包含多重条件判断的程序,最简单的测试准则是设计出足够数量的测试用例,将每个判断的所有可能的条件结果的组合,以及所有入口点都至少执行一次。
二、黑盒测试方法 等价划分 测试用例是为了从所有的可能输入中找出可能发现最多错误的子集。确定这个子集的一种方法,就是要意识到一个精挑细选的测试用例还应具备另外两个特征: 1)严格控制测试用例的增加,减少为达到“合理测试”的某些既定目标而必须设计的其他测试用例的数量。(每个测试用例都必须体现尽可能多的不同的输入情况,以使最大限度地减少测试所需地全部用例数量) 2)它覆盖了大部分其他可能的测试用例。也就是说,它会告诉我们,使用或者不使用这个特定的输入集合,哪些错误会被发现,哪些会被遗漏掉。(应该尽量将程序输入范围进行划分,将其划分为有限数量的等价类,这样就可以合理地假设测试每个等价类的代表性数据等同于测试该类的其他任何数据,即若等价类的某个测试用例发现了某个错误,该等价类的其他用例应该也能发现同样的错误,相反,如果测试用例没能发现错误,那么我们可以预计,该等价类中的其他测试用例不会出现在其他等价类中,因为等价类是相互交迭的) 步骤:1)确定等价类;2)生成测试用例
确定等价类 选取每一个输入条件(通常是规格说明中的一个句子或短语)并将其划分为两个或更多的组。有效等价类代表对程序的有效输入,无效等价类要注意不正确以及未预料到的输入情况。在给定了输入或者外部条件之后,确定等价类大体上是一个启发式的过程。 确定等价类的原则: 1)如果输入条件规定了一个取值范围(例如,数量可以是从1到999),那么就应确定出一个有效等价类(1<数量<999),以及两个无效等价类(数量<1,数量>999)。 2)如果输入条件规定了取值的个数(例如,汽车可登记一至六名车主),那么就应确定出一个有效等价类和两个无效等价类(没有车主,或车主多于六个)。 3)如果输入条件规定了一个输入值的集合,而且有理由认为程序会对每个值进行不同处理(例如,交通工具的类型必须是公共汽车、卡车、出租车、火车或摩托车),那么就应为每个输入值确定一个有效等价类和一个无效等价类(例如,拖车)。 4)如果存在输入条件规定了“必须是”的情况(例如,标识符的第一个字母必须是字母),那么就应确定一个有效等价类(首字符是字母)和一个无效等价类(首字符不是字母)。 如果有任何理由可以认为程序并未等同地处理等价类中的元素,那么应该将这个等价类再划分为小一些的等价类。生成测试用例 1)为每个等价类设置一个不同的编号。 2)编写新的测试用例,尽可能多地覆盖那些尚未被覆盖地有效等价类,直到所有的有效等价类都被测试用例所覆盖(包含进去)。 3)编写新的测试用例,覆盖一个且仅一个尚未被覆盖的无效等价类,直到所有的无效等价类都被测试用例所覆盖。(用单个测试用例覆盖无效等价类,是因为某些特定的输入错误检查可能会屏蔽或取代其他输入错误检查。) 尽管等价划分方法要比随机选取测试用例优越得多,但它仍然存在不足。例如,这种方法忽略掉了某些特定类型的高效测试用例。边界值分析与因果图可以弥补其中的很多不足。 边界值分析 经验证明,考虑了边界条件的测试用例与其他没有考虑边界条件的测试用例相比,具有更高的测试回报率。所谓边界条件,是指输入和输出等价类中那些恰好处于边界、或超过边界、或在边界以下的状态。边界值分析方法和等价划分法存在两方面的不同: 1)与从等价类中挑选任意一个元素作为代表不同,边界值分析需要选择一个或多个元素,以便等价类的每一个边界都经过一次测试。 2)与仅仅关注输入条件(输入空间)不同,还需要考虑从结果空间(输出等价类)设计测试用例。 边界值分析考察正处于等价划分边界或在边界附近的状态。 能够提供部分帮助的通用指南: 1)如果输入条件规定了一个输入值范围,那么应针对范围的边界设计测试用例,针对刚刚越界的情况设计无效输入测试用例。 2)如果输入条件规定了输入值的数量,那么应针对最小数量输入值、最大数量输入值,以及比最小数量少一个、比最大数量多一个的情况设计测试用例。 3)对每个输出条件 应用指南1。设计测试用例诱导其输出指南1的错误结果。 4)对每个输出条件 应用指南2。 5)如果程序的输入或输出是一个有序序列(例如顺序的文件、线性列表或表格),则应特别注意该序列的第一个和最后一个元素。 6)此外,发挥聪明才智找出其他边界条件。
因果图 边界值分析和等价划分的一个弱点是未对输入条件的组合进行分析。因果图有助于用一个系统的方法选择出高效的测试用例集。它还有一个额外的好处,就是可以指出规格说明的不完整性和不明确之处。 因果图是一种形式语言,用自然语言描述的规格语言可以转换为因果图。因果图实际上是一种数字逻辑电路(一个组合的逻辑网络),但没有使用标准的电子学符号,而是使用了稍微简单点的符号。 生产测试用例的过程如下: 1)将规格说明分解为可执行的片段。 2)确定规格说明中的因果关系。所谓“因”,是指一个明确的输入条件或输入条件的等价类。所谓“果”,是指一个输出条件或系统转换(输入对程序或系统状态的延续影响,举例来说,如果某个事务引起文件或数据库记录被修改,那么这种改变就是一个系统转换,而系统反馈的确认信息就是一个输出条件)。因果关系一旦确定下来,每个“因”和“果”都被赋予一个唯一的编号。 3)分析规格说明的语义内容,并将其转换为连接因果关系的布尔图。就是所谓的因果图。 4)给图加上注解符号,说明由于语法或环境的限制而不能联系起来的“因”和“果”。 5)通过仔细地跟踪图中地状态变化情况,将因果图转换成一个有限项的判定表。表中每一列代表一个测试用例。 6)将判定表中的列转换为测试用例。
因果图中最具难度的部分是将因果图转化为判定表,这个过程现在已经有算法可以编程完成。 回看《软件测试的艺术》里面关于因果图的例题!!!
错误猜测 错误猜测主要是一项依赖于直觉的非正规的过程,因此很难描述出这种方法的规程。其基本思想是列举可能犯的错误或错误易发生情况的清单,然后依据清单来编写测试用例。
测试策略总结 测试用例设计方法可以组合为一个整体的策略,一组合理的策略如下:
如果规格说明中包含输入条件组合的情况,应首先使用因果图分析法。 在任何情况下都应使用边界值分析方法。硬棘蛛,这是对输入和输出边界的分析。边界值分析可以产生一系列补充的测试条件,但是,也正如因果图分析中所说,多数乃至全部边界条件都可以被整合到因果图测试分析中。 应为输入和输出确定有效和无效等价类,在必要情况下对上面确认的测试用例进行补充。 使用错误猜测技术增加更多的测试用例。 针对上述测试用例集检查程序的逻辑结构。应使用判定覆盖、条件覆盖、判定/条件覆盖或多重条件覆盖准则(最后一个最为完整)。如果覆盖准则未能被前四个步骤中确定的测试用例所满足,并且满足准则也并非不可能(由于程序的性质限制,某些条件的组合也许是不可能实现的),那么增加足够数量的测试用例,以使覆盖准则得到满足。 按照开发阶段分类 构建大型程序测试的第一个步骤:模块测试
一、模块(单元)测试——详细设计阶段 模块测试(单元测试)是对程序中的单个子程序、子程序或过程进行测试的过程。目的是将模块的功能与定义模块的功能规格说明或接口规格说明进行比较,以此揭示模块与其规格说明存在着矛盾。
测试用例设计 在为模块测试设计测试用例时,需要使用两种类型的信息:模块的规格说明和模块的源代码。规格说明一般都规定了模块的输入和输出参数以及模块的功能。 设计过程: 1)使用一种或多种白盒测试方法分析模块的逻辑结构;(多重条件覆盖准则要优于其他准测,任何逻辑覆盖准则尚不足以胜任作为生成模块测试用例的唯一手段,因此下一个步骤就是用一组黑盒测试用例来补充) 2)使用黑盒测试方法对照模块的规格说明以补充测试用例。
增量测试 在执行模块测试过程中,我们主要有两点考虑:1)如何设计一个有效的测试用例集;2)将模块组装成工作程序的方式。第二点很重要,因为它设计模块测试用例的编写形式、可能用到的测试工具类型、模块编码和测试的顺序、生成测试用例的成本以及调试(定位并修复检查出的错误)的成本等。组装方法有:非增量测试和增量测试,增量测试又分为自顶向下和自底向上的开发或测试过程。
非增量测试 (崩溃测试)即先独立地测试每个模块,然后再将这些模块组装成完整的程序。 测试单独的模块需要一个特殊的驱动模式(driver module)和一个或多个桩模块(stub module)。例如测试B模块,首先要设计测试用例,然后将测试用例作为输入参数由驱动模块传递给模块B。驱动模块是人们编写的一个小模块,用来将测试用例驱动或传输到被测模块中(也可以用测试工具替代)。驱动模块还必须向测试人员显示B模块的测试结果。此外,由于模块B调用了模块E,所以还必须使用一个额外的组件,该组件在模块B调用模块E时接受模块B的控制指令。这就由桩模块来完成,它是一个被命名为"E"的特殊模块,用来模拟模块E的功能。当所有6个模块的模块测试都完成之后,就将这些模块组装成完整的程序。
增量测试 (集成)不同于独立测试每个模块,增量测试首先将下一个要测试的模块组装到前面已经测试过的模块集合中去。
非增量测试与增量测试的比较: 1)非增量测试所需的工作量要多一些,因为增量测试使用了前面测试过的模块来取代非增量测试中所需要的驱动模块(如果从顶部开始测试)或桩模块(如果从底部开始测试)。 2)如果使用了增量测试,可以较早地发现模块中与不匹配接口、不正确假设相关的编程错误 。这是由于尽早地对模块组合进行了集成测试。然而,如果采用非增量测试,只有到了测试过程的最后阶段,模块之间才能“相互看到”。 3)因此,如果使用了增量测试,调试会进行得容易一些 。我们假设存在着与模块间接口或假设相关的编程错误,那么,如果使用非增量测试,直到整个程序组装之后,这些错误才会浮现出来。到了这个时候,我们就难以定位错误,因为它可能存在于程序内部的任何位置。相反,如果使用增量测试,这种类型的错误就很容易发现,因为该错误很可能与最近添加的模块相关。 4)增量测试会将测试进行得更彻底 。如果当前正在测试模块B,要么是模块E,要么是模块A(取决于测试是从底部还是从顶部开始的)被当作结果执行,则会诱发一个新的情况,可能会暴露出先前测试过的模块E或模块A中存在的一个新缺陷。另一方面,如果使用的是非增量测试,对模块B的测试仅影响到其本身。换言之,增量测试使用先前测试过的模块,取代了非增量测试中使用的桩模块或驱动模块。因此,到最后一个模块测试完成时,实际的模块受到了更多的检验。 5)非增量测试所占用的机器时间显得少一些 。如果使用自底向上的方法测试图5-7中的模块A,在执行A的过程中,模块BCDEF也会执行到。因此,完成一次增量测试所需执行的机器指令显然比非增量测试多,但是非增量测试要比增量测试需要更多的驱动模块和桩模块,开发这些时要占用机器时间的。 6)模块测试阶段开始时,如果使用的是非增量测试,就会有更多的机会进行并行操作(也就是说,所有的模块可以同时开始测试) 。对于大型的软件项目(模块和人员都很多),这可能十分重要,因为在模块测试开始之时,项目的人员数量常常处于最高峰。 其中1)-4)是增量测试的优点,5和6是缺点,但是考虑到计算机行业当前的趋势,再考虑到错误发现得越早,改正它的成本也越低,1-4的重要性日益突出,5显得不那么重要,6似乎是一个薄弱的缺点。我们可以得出结论,增量测试会更好。
增量测试可以分为自顶向下测试和自底向上测试。
自顶向下测试 自顶向下的测试是从程序的顶部或初始模块开始。测试开始之后,挑选哪个后续模块进行增量测试没有唯一正确的方法,唯一的原则是:要成为合乎条件的下一个模块,至少一个该模块的从属模块(调用它的模块)事先经过了测试。 第一步是测试模块A,测试要求必须编写出代表B、C和D的桩模块。 首先需要考虑的问题是桩模块的编写,桩模块不能仅仅只存在而不起任何作用,而是应该模拟出相应的模块,例如返回一个有意义的结果等等。 另一个需要考虑的地方是采取什么样的形式将测试用例提交给程序,例如此处,测试数据是通过其一个或多个桩模块提交给模块的(此处为模块A)。为了说明这一点,假设模块B:获取事物文件的概要;模块C:判断每周的状态是否满足限额;模块D:生成每周总结报告。那么自桩模块B返回的一个事务概要就是模块A的一个测试用例。桩模块D可能包含将其输入数据写到打印机的语句,这样就可以检查每一个测试的结果。 在本程序中还存在另一个问题。由于假定模块A仅调用模块B一次,问题是如何将多个测试用例提交给模块A。一个解决方法是编写出桩模块B的多个版本,每一个版本都将一个各不相同的有效测试数据集返回给模块A。为了执行这些测试用例,程序需要执行多次,每次都使用桩模块B的不同版本。另一种可选择的方法是将测试数据放置在外部文件中,由桩模块B读取并返回给模块A。对于任何一种情况,开发桩模块通常要比实际理解的更为困难,而且,由于程序的特点所致,通过被测模块之下的多个桩模块来传送测试数据常常是必需的(即被测模块通过调用多个桩模块来获得要处理的测试数据)。 模块A测试完成之后,就用一个实际的模块代替其中的一个桩模块,而该模块需要的桩模块也被添加进来。举例来说,以下就显示了该程序的下一版本: 测试完成顶部模块之后,接下来可能的测试序列有很多。举例来说,如果我们要执行所有的测试序列,大量可能的模块序列中的四个序列如下: 1)ABCDEFGHIJKL 2)ABEFJCGKDHLI 3)ADHIKLCGBFJE 4)ABFJDIECGKHL 总的来说,不存在最佳的模块序列,但却有下面可供考虑的两项指南: 1)如果程序中存在关键模块(例如模块G),那么在设计模块序列时就应将这些关键模块尽可能地早添加进去。所谓“关键部分”可能时某个复杂的模块、某个采用新算法的模块或某个容易发生错误的模块。 2)在设计模块序列时,应将I/O模块尽可能地早添加进来。(桩模块的问题就是一部分桩模块必须包含测试用例,而另一部分桩模块则须将其输入写到打印机中或显示出来。然而,接收程序输入的模块一旦被添加进来,测试用例的描述就相当简单了;其采用的形式就与最终程序接收的输入一样。相似地,一旦执行程序输出功能的模块被添加进来,桩模块就可能无需再放置输出测试用例结果的代码。) 因此,如果模块I、J是I/O模块,而模块G执行某些关键操作,那么增长序列可能是: ABFJDICGEKHL 那么就会到达下图所示的中间阶段: 由于现在程序有一个实际运行的框架版本,也就是执行实际的输入和输出操作。这个早期的程序框架版本有以下优点: 可以使我们发现认为因素的错误和问题; 可以将程序演示给最终用户看; 证明程序的整体设计是合理的; 起到精神上的鼓舞作用。 然而,自顶向下策略还有一些严重的缺陷,例如我们假定当前的测试状态如5-10所示,下一步是用模块H取代桩模块H。 这时,我们要做的是使用本章前面所述的方法为H设计一个测试用例集。但是请注意,这些测试用例采用的是向模块J的实际程序输入的形式。这带来了一些问题。 首先,由于在模块J和模块H之间存在中间模块(即模块F、B、A和D),我们会发现无法将测试过模块H中所有预先确定的情况的测试用例提交到模块J中去。 其次,由于H和程序中测试数据引入点之间存在着“距离”,即使存在着测试全部状态的可能性,要决定往模块J中输入什么样的数据来测试到H中的所有状态,通常也是一项困难的脑力劳动。 最后,由于一个测试显示出来的输出可能来自于一个与被测模块相距甚远的模块,要将显示出来的输出与此模块的实际执行情况联系起来非常困难,甚至是不可能的。 自顶向下的测试策略取决于其使用的方法,可能还存在两个更深层次的问题。人们会偶尔感觉到它可能与程序的设计阶段重叠 。举例来说,如果我们正在设计如图5-8所示的程序,可能会觉得在最先的两个层次设计完成之后,在下面层次的设计进行的同时就可以对模块A至模块D进行编码和测试了。正如我们在其他地方所强调的那样,这往往不是明智之举。程序设计是一个迭代的过程,这意味着当我们在设计程序结构的较低层次时,可能会对较高层次进行合理的变更或改进。如果较高层次已经完成了编码和测试,那么这些理想的改进就会被摈弃,最终成为一个不明智的决策。 在进行到下一个模块前未能穷举测试此模块 。这来自于两个原因:一时由于将测试数据嵌入桩模块中存在困难,二是由于程序的较高层次通常会为较低层次提供资源。可能会将较高层次的某些测试延后,但是等到了那个较晚的时间点,很多人就会忘记较高层次未完成的测试内容。另外,因为较高层次常会提供资源给较低层次使用(例如打开文件),有时除非到了使用资源的较低层次模块测试完场之后,我们很难判断这些资源提供得是否正确(例如,文件是否以正确的属性打开)。 自底向上的测试 在大多数情况下,自底向上与自顶向下的策略是相对立的,自顶向下测试的优点成为自底向上测试的缺点,反之亦然。 自底向上的策略开始于程序中的终端模块。测试完这些模块之后,同样没有最佳的方法来挑选要进行增量测试的下一个模块。唯一正确的原则是,要成为合乎条件的下一个模块,该模块所有的从属模块(它调用的模块)都已经事先经过了测试。 如上图,第一步测试E、J、G、K、L和I中的部分或全部模块,既可以串行测试,也可以并行进行。要做到这一点,每一个模块都需要一个特殊的驱动模块:即包含着有效的测试输入、调用被测模块且将输出显示出来(或将实际输出与预期输出作比较)的模块。有别于使用桩模块的情况,由于驱动模块可以交迭地调用被测模块,因此不需要为驱动模块提供多个版本。在大多数情况下,开发驱动模块要比开发桩模块更容易一些。 影响测试序列的因素是模块的关键程度。 自底向上策略的一个不足是,它没有早期程序框架的概念 。事实上,知道最后一个模块被添加进来,才形成了可工作的程序。尽管I/O功能可以在整个程序集成之前进行测试,早期程序框架的优点在这里体现不出来。 自顶向下方法中无法建立所有测试环境的问题,在这里都不复存在。如果将驱动模块看作是一个测试指针的话,那么该探针是直接放入被测模块中去的,不会受到中间模块的困扰。同时不会作出让设计和测试重叠的不明智决定,因为自底向上的测试要直到程序底层设计完成之后方才开始。同样,在没有测试完一个模块之前就开始另一个模块测试的问题也不会存在,这是因为自底向上的测试不再有如何将测试数据绑定到桩模块中去的烦恼。
比较 每种方法的第一个优点似乎是决定性的因素,但是也没有证据表明主要的缺陷会更容易发生在典型程序的顶部或底部。 最保险的判定使用哪种方式的方法是,根据特定的被测程序,对上表中所示的各因素进行权衡。由于这里缺乏一个规程,自顶向下测试第四个缺点的严重后果,以及有可用的测试工具减少了对驱动模块而不是桩模块的需求,这样似乎给自底向上的策略带来了优势。 除此之外,自顶向下的方法和自底向上的方法很显然都不是唯一可能的增量测试策略。
执行测试 模块测试的其他部分如何实际进行测试。一系列操作的提示和指南:
当测试用例造成模块输出的实际结果与预期结果不匹配的情况时,存在两个可能的解释:要么该模块存在错误,要么预期的结果不正确(测试用例不正确)。为了将这种混乱降低到最小程度,应在测试执行之前对测试用例集进行审核或检查(也就是说,对测试用例进行测试)。 使用自动化测试工具可以使测试过程中的枯燥劳动减至最小。举例来说,现在已有测试工具可以降低我们对驱动模块的需求。流程分析工具可以列举出程序中的路径,找到从未被执行的语句(“不可达”代码),以及找出变量在赋值前被使用的实例。 对预期输出进行定义时测试用例必不可少的部分。在执行测试时,应该查找程序的副作用(即模块执行了某些不该执行操作的情况)。一般情况下,这些情况都是很难发现的,但如果在测试用例执行完之后,检查那些不应有变动的模块输入,可能会发现一些错误实例。 因个人试图测试自己编写的程序所带来的心理学问题,也适用于模块测试。程序员不应测试自己编写的模块,而应交换模块进行测试,编写调用模块的程序员始终时测试被调用模块的最佳候选人。注意,这仅仅适用于测试,对模块的调用一般应当由编程人员本人进行。应避免随意丢弃测试用例,应将它们按某种格式记录下来,以便将来可以重新使用它们。如果发现某一部分模块存在大量错误,那么很有可能这些模块甚至包含着更多错误,这样的模块应该进行更进一步的测试,可能还需要进行额外的代码走查或检车。最后,记住模块测试的目的不是证明模块能够正确地运行,而是证明模块中存在着错误。 二、更高级别的测试 完成了对程序的模块测试之后,整个测试过程才刚刚开始,对于大型或负责的软件来说尤为如此。**当程序无法实现其最终用户要求的合理功能时,就发生了一个软件错误。**因此,要结束整个测试任务,还须进行其他形式的更深入的测试,我们将其称为“更高级别的”测试。 软件开发过程在很大程度上是沟通有关最终程序的信息,并将信息从一种形式转换到另一种形式。由于这个原因,绝大部分软件错误都可以归因于信息沟通和转换时发生的故障、差错和干扰。 软件开发过程可以归纳为以下七个步骤:
将软件最终用户的要求转换为一系列书面的需求。这些需求就是该软件产品要实现的目标。 通过评估可行性与成本、消除相抵触的用户需求,建立优先级和平衡关系,将用户需求转换为具体的目标。 将上述目标转换为一个准确的产品规格说明,将产品视为一个黑盒,仅考虑其接口以及与最终用户的交互。该规格说明被称为“外部规格说明”。 如果该产品是一个系统,如操作系统、飞行控制系统、数据库管理系统或雇员人事系统等,而不是一个程序(编译器、工资程序、字处理程序等),那么下一步骤就是系统设计。该步骤将系统分割为单独的程序、部件或子系统,并定义它们的接口。 通过定义每个模块的功能、模块的层次结构及模块间的接口,来设计程序或程序集合的结构。 设计一份准确的规格说明,定义每个模块的接口与功能。 经过一个或更多的子步骤,将模块接口规格说明转换为每个模块的源代码算法。 需求规格说明定义了为什么要开发程序。 目标定义了程序要做什么,以及应做得怎么样。 外部规格说明定义了程序对用户的准确表现。 与后续阶段相关的文档越来越详细地规定了程序是如何建立起来的。 假定软件开发周期的七个阶段包括了信息的沟通、理解和转换,以及大多数的软件错误都来源于信息处理中的故障,那么现在有三个补充的方法来预防或识别这些错误: 可以使软件开发过程更精密,以防其中出现更多错误。 在每个阶段进入下一阶段之前尽可能多地发现问题。 对不同地开发阶段采用不同地测试方法。 1. 集成测试——概要设计阶段 集成测试往往不作为一个独立的测试步骤,而且在进行增量模块测试时,它时模块测试的隐藏部分。
2. 功能测试 **功能测试是一个试图发现程序与其外部规格说明之间存在不一致的过程。**外部规格说明是一份从最终用户的角度对程序行为的精确描述。 功能测试通常是一项黑盒操作。在进行功能测试时,需要对规格说明进行分析以获取测试用例集。等价类划分、边界值分析、因果图分析和错误猜测的方法尤其适合于功能测试。还有一些原则也特别适合于功能测试:跟踪那些暴露出错误数量最多的功能,这些功能很可能还包含着大多数尚未发现的错误。应记住对无效和未预想到的输入条件给予足够的重视。对预期结果的定义是测试用例的重要部分。最后,应始终牢记功能测试的目的是为了暴露程序的错误以及与规格说明不一致之处,而不是为了证明程序符合其外部规格说明。
3. 系统测试 系统测试最容易被错误理解,也是最困难的测试过程。系统测试的目的:将系统或程序与其初始目标进行比较。给定这个目标之后,隐含两方面的含义: 1)系统测试并不局限于系统。如果产品时一个程序,那么系统测试就是一个试图说明程序作为一个整体时如何不满足其目标的过程。 2)根据定义,如果产品没有一组书面的、可度量的目标,系统测试也就无法进行。 在寻找程序与其目标不一致的过程中,应重点注意那些在设计外部规格说明的过程中所犯的转换错误。 与功能测试不同,外部规格说明不能作为获得系统测试的基础,否则就破坏了系统测试的目标。另一方面,也不能利用目标文档本身来表示测试用例,因为根据定义,这些文档并不包含对程序外部接口的准确描述。 克服上述两个困难的方法是利用程序的用户文档或书面材料。通过分析目标文档来设计系统测试,分析用户文档来阐明测试用例。 图6-4中,最左边的箭头表示将程序与其目标进行比较,是系统测试的核心目的,但是没有说明使用什么样的测试用例方法。因为目标文档阐述了程序应该做什么、做到什么程度,却没有说明程序功能如何表现。因此,系统测试采取了一种不同的测试用例设计方法,不是描述一项技术,而是讨论不同类型的系统测试用例:
能力测试。逐条语句地检查目标文档,当某条语句定义了一个“要做什么”,就判断程序是否满足。这种类型的测试常常可以在不使用计算机的情况下进行,有时人工对目标和用户文档进行比较就足够了。利用问题检查单将有助于在下一次进行测试时,确保人工检查的目标时相同的。 容量测试。使程序经受大容量数据的检验,目的是为了证明程序不能处理目标文档中规定的数据容量。 强度测试。使程序承受高负载或强度的检验,这里所谓的高强度是指在很短的时间间隔内达到的数据或操作的数量峰值,与容量测试不同。基于Web的应用程序时最常接受强度测试的软件之一。 易用性测试。试图发现人为因素或易用性问题。一些需要测试的问题: 每个用户界面是否都根据最终用户的智力、教育背景和环境要求进行了调整? 程序的输出是否有意义、不模糊且没有计算机的杂乱信息? 错误诊断是否直接,用户是否需要有计算机学科的博士学位才能理解它? 整体的用户界面是否在语法、惯例、语义、格式、风格和缩写方面展现出了相当程度的概念完整性、基本性、一致性和统一性? 在准确性极为重要的环境里,如网上银行系统,输入中是否有足够的冗余信息? 系统是否包含过多或不太可能用到的选项? 对于所有的输入,系统是否返回了某些类型的即时确认信息? 程序是否易于使用? 安全性测试。设计测试用例来突破程序安全检查的过程。基于Web的应用程序常常比绝大多数程序所需的安全测试级别更高。对于电子商务网站尤其如此。 性能测试。很多软件都有特定的性能或效率目标,这些特性描述为在特定负载和配置环境下程序的响应时间和吞吐率,性能测试就是设计测试用例来说明程序不能满足其性能目标。 存储测试。诸如操作系统、数据库管理系统和信息交换系统等软件都支持多种硬件配置,包括不同类型和数量的I/O设备和通信线路,或不同的存储容量,通常可能的配置数量非常之大,以致于测试无法面面俱到,但是至少应该使用每一种类型的设备,以最大和最小的配置来测试程序。如果软件本身的配置可忽略掉某些程序组件,或可运行在不同的计算机上,那么该软件所有可能的配置都应测试到。 兼容性/配置/转换测试。 安装测试。 可靠性测试。 可恢复性测试。诸如操作系统、数据库管理系统和远程处理系统等软件通常都有可恢复性目标,说明系统如何从程序错误、硬件失效和数据错误中恢复过来。 适用性测试。软件还可能有适用性或可维护性的目标,这些目标可能定义了系统提供的服务辅助功能,包括存储转存程序或诊断程序、调试明显问题的平均时间、维护过程以及内部业务文档的质量等。 文档测试。检查文档的正确性。 过程测试。在系统测试中,必须对所有已规定的人工过程,如系统操作员、数据库管理员或最终用户的操作过程进行测试。 系统测试的执行。1)不能由程序员来进行系统测试;2)在所有的测试阶段中,这是唯一一个不能由该程序开发的机构来执行的测试。 4. 验收测试 验收测试是将程序与其最初的需求及最终用户当前的需求进行比较的过程。对于软件按合同开发的情况,由订购方(用户)来进行验收测试,将程序的实际操作与原始合同进行对照。验收测试最好的方法是设计测试用例,尽力证明程序没有满足合同要求;假如这些测试用例都是不成功的,那么就可以接受该程序。
5. 安装测试 安装测试应由生产软件系统的机构来设计,作为软件的一部分来发布,在系统安装完场之后进行。除此之外,测试用例需要检查以确认已选的选项结合互不冲突,系统的所有部件全部存在,所有的文件已经创建并包含必须内容,硬件配置妥当等。
6. 测试的计划与控制 一个良好的测试计划应包括:
目标。必须定义每个测试阶段的目标。 结束准则。必须制定准则以规定每个测试阶段何时可以结束。 进度。每个阶段都必须有时间表。应指出何时设计、编写和执行测试用例。 责任。对于每一个阶段,应当确定谁来设计、编写和验证测试用例,谁来修改发现的软件错误。 测试用例库及标准。 工具。 计算机时间。 硬件配置。 集成。 跟踪步骤。 调试步骤。 回归测试。 三、调试 定位错误;修改错误。
1. 暴力法调试 利用内存信息输出来调试。 根据一般的“在程序中插入打印语句”建议来调试。 使用自动化的调试工具进行调试。 主要问题:它们都忽略了思考的过程。建议仅在下列情况下使用暴力调试方法:其他的方法都失败了;作为下面调试方法的补充,而不是替代方法。 2. 归纳法调试 归纳是一种特殊的思考过程,可以从细节转到全局,也就是从线索出发,寻找线索之间的联系。
3. 演绎法调试 演绎的过程是从一些普遍的理论或前提出发,使用排除和精炼的过程,达到一个结论(错误的位置)。
4. 回溯法调试 从程序产生不正确结果的地方开始,从该处观察到的结果推断出程序变量应该是些什么值。在头脑中,从这个位置开始逆向执行程序,定位出错误。
5. 测试法调试 供测试的测试用例,其目的是暴露出以前尚未发现的错误;供调试的测试用例,其目的是提供有用的信息,供定位某个被怀疑的错误之用。供测试的测试用例会“胖”一些,因为我们尽量使用较少数量的测试用例来涵盖较多的条件,而供调试的测试用例则“瘦”一些,因为每个测试用例仅需要覆盖一个或几个条件。当发现了某个被怀疑的错误的症状之后,我们需要编写与原先有所变化的测试用例,尽量确定错误的位置。它常常与归纳法一起使用,也可与演绎法一起使用。
6. 定位错误的原则 动脑筋 如果遇到了僵局,就留到稍后解决 如果遇到了困境,就把问题描述给其他人听 仅将测试工具作为第二种手段 避免使用试验法——将其作为最后的手段 7. 修改错误的技术 存在一个缺陷的地方,很可能还存在其他缺陷。 应纠正错误本身,而不是其症状。 正确纠正错误的可能性并非100% 正确修改错误的可能性随着程序规模的增加而降低 应意识改正错误会引入新错误的可能性 修改错误的过程也是临时回到设计阶段的过程 应修改源代码,而不是目标代码 8. 错误分析 调试除了有消灭程序中错误的价值之外,还有其他重要信息:它可以告诉我们软件错误的一些本质,我们对此了解得非常之少。关于软件错误本质的信息可以为改进将来的设计、编码和测试过程提供有价值的反馈信息。错误分析应该包括:
错误出现在什么地方?它需要通过对程序文档和项目历史进行回溯研究,但同时它也是最有价值的问题。它要求我们之处该错误的源头和发生时间。 谁制造了这个错误? 哪些做得不正确?要准确地判断出错误发生的原因。 如何避免该错误的出现? 为什么错误没有早些发现? 该如何更早地发现错误? 极限测试 极限编程(XP)是到目前为止最流行的敏捷软件开发过程,XP开发方法的目的是在短时间那内开发高质量的程序。XP模型高度依赖模块的单元和验收测试,对每个无论多小的递增的代码变更,都必须进行单元测试,以确保代码库满足其规格说明要求。事实上,测试在XP中的地位非常重要,以至于需要首先创建单元测试和验收测试,然后才创建代码库,这种形式的测试被称为极限测试(XT)。
1. 极限单元测试 两个简单规则:所有代码模块在编码开始之前必须设计好单元测试用例,在产品发布之前须通过单元测试。极限测试中的单元测试必须在模块编码之前就完成设计和生产。开始编码之前设计单元测试有一些好处:
获得了代码将满足其规格说明的信心。 在开始编码之前,就展现了代码的最终结果。 更好地理解了应用程序的规格说明和需求。 可以先实现一些简单的设计,稍后再放心地重构代码以改善程序的性能,而无须担心破坏应用程序的规格说明。 2. 验收测试 验收测试的目的是判断应用程序是否满足如功能性和易用性等其他需求。在设计/计划阶段,由开发人员和客户来设计验收程序。与其他测试形式不同,验收测试是由客户,而不是开发人员或编程搭档来执行的。在这种方式中,客户对应用程序是否满足他们的要求进行客观、公开的确认。客户通过使用场景来设计验收测试,使用场景与验收测试之比通常是一对多。
测试因特网应用系统 测试基于因特网的应用系统的目标与测试传统程序并没有什么区别,必须在程序部署到因特网之前暴露其中存在的错误。
1. 电子商务的基本结构
2. 测试的挑战 用户群体庞大且五花八门。网站用户的能力参差不齐,使用的浏览器、操作系统和设备种类也不同,我们还应考虑到消费者访问网站时的信道速率差别也很大。 业务环境。如果运行的是一个电子商务网站,那么必须考虑到诸如计算税费、判断运输成本、结算往来账务以及跟踪用户资料等问题。 地点。用户可能位于其他国家,在这种情况下,涉及到处理国际化问题,如语言翻译、时差及货币兑换等问题。 测试环境。为了严格地测试应用系统,必须复制软件运行的环境,即使用与软件运行环境中相同的Web服务器、应用服务器和数据库服务器。为了得到最精确的测试结果,还需要建立相同的网络环境,包括路由器、交换机和防火墙。 安全相。 测试浏览器的兼容性 3. 测试的策略 为基于因特网的应用系统涉及测试策略,需要对组成应用系统的每一个硬件和软件组件都有深入的了解。规格说明文档对于成功测试一般的应用程序非常关键,这里也需要一份规格说明文档来描述Web站点的预期功能和性能。 按照因特网应用系统的三层C/S程序进行分层测试:
表示层的测试 主要目的是发现应用程序的GUI或前端错误。下面列举了表示层测试中的三个主要内容: 内容测试。包括整体审美、字体、色彩、拼写、内容准确性和默认值。 Web站点结构。包括无效的连接或图形。 用户环境。包括Web浏览器的版本和操作系统配置。(也被称为“浏览器兼容性测试”)常常是测试基于因特网的应用系统中最具挑战性的部分。浏览器和操作系统的组合非常之多,我们不仅要测试每一个浏览器的配置,还要测试同一个浏览器的不同版本。如果浏览器系统高度依赖客户端的脚本处理,用户环境测试就变得更加复杂,每一个浏览器都有不同的脚本引擎或虚拟机在客户计算机上运行脚本和代码。如果使用了一下任何一项,就应特别关注浏览器的兼容性问题:ActiveX控件;Javascript;Vbscript;Java applets 。通过制订定义完善的功能需求,可以客服大多数与浏览器兼容性测试相关的挑战。举例来说,在需求搜集阶段,市场部门可能会决定应用系统只需要运行于几个特定的浏览器就可以了,这个需求排除了大量的测试工作量,因为我们有了一个定义良好的目标平台以供测试。 业务层测试 业务层测试的重点是发现因特网应用系统的业务逻辑错误。白盒、黑盒测试技术都可以使用到,我们需要制定测试计划和过程,用来发现系统性能需求、数据获取和事务处理中的错误。 对于内部开发的部件,可以深入程序逻辑结构中去,因此应该使用白盒测试,然而,黑盒测试技术应是业务层测试的主要方法。在对业务层进行系统测试时,需要模拟用户在购买某个产品或服务时执行的步骤。我们应该采用多种测试方法进行测试,无论采用什么方法,应用系统中始终存在着一些可以测试的特性,这些内容包括: 性能 。测试的目的在于检查应用系统是否满足书面性能规格说明(通常定义为响应时间和吞吐率)。为了达到足够的性能水平,必须保证性能规格说明在需求收集阶段编写完成,如果没有书面的规格说明或目标,也就无从得知应用系统的性能是否可以接受。强度测试是一种常用的性能测试方法。开始进行强度测试之前,应确保支撑设施部件处于合适状态,如果做不到这一点,可能会得到错误的结果。数据有效性 。测试的目的在于发现从用户那里采集到的数据中的错误。事务 。测试的目的在于发现事务处理过程中的错误,其中可能包括信用卡处理、电子邮件验证以及消费税计算等。我们可以将事务测试视为对业务层进行的系统测试,自始自终测试业务层,尽量发现错误。再次强调,应具备书面的文档,详细定义事务的构成,除了测试内部的业务过程之外,还必须测试外部服务。 数据层测试 数据层测试主要是指对应用系统用于存储和获取信息的数据库管理系统的测试。数据测试的最大挑战之一是复制应用系统的运行环境。必须使用相同的硬件平台和软件版本来进行有效的测试,此外,一旦获得了资金和人力资源,就必须设计一个方法来使实际运行的环境与测试环境保持一致。与测试其他层一样,在测试数据层时应当在特定的方面查找错误: 响应时间 。应量化数据操作语言(DML,包括结构化查询语言SQL中的INSERT、UPDATE和DELETE)、查询(SELECT)及事务的完成时间。在测试数据层的响应时间时,我们要确保单个的数据库操作能够快速完成,不至于阻塞其他操作。对数据层响应时间的测试充斥着挑战。测试环境必须与系统实际应用环境相一致,否则得到的结果就会无效。另外,必须彻底了解数据库系统,确保它安装正确、操作有效。数据完整性 。即在数据库表中发现不准确数据的过程,验证数据存储适当且正确。有很多因素会影响到数据库存储数据的方式,数据类型和长度可能导致数据截断或食去精确性;对于日期和时间字段,会出现时区问题;国际化和字符集同样会影响数据完整性;还应检查应用系统使用的检查/参考表的准确性,例如销售税、邮政编码及时区信息等。我们不仅要确保信息准确,还应保持其最新。容错性和可恢复性 。最大化平均故障间隔时间(MTBF),最小化平均故障恢复时间(MTTR)。最大化MTBF取决于数据库系统的容错级别,采用何种类型的测试取决于系统的结构。可恢复性测试的目标是设计出数据库无法恢复的场景出来,恢复计划开始于获得有效的备份,在进行可恢复性测试时,如果无法恢复数据库,那么需要修改备份策略。 软件测试实例 电商系统(用户)
三角形判定