您好,欢迎访问三七文档
提纲1.序言2.一个单元测试示例3.测试内容及方法4.边界条件5.单元测试工具6.Mock对象7.好的测试品质8.在项目中进行测试序言(1)要向客户演示系统的基本功能,且临近最终期限时,两个开发者的两种不同的做法:第一个开发者:每天着急地写代码,写完一个类又写一个类,写完一个方法又接着写两一个方法,有时不得不停下来做一些调整,使得代码能够编译通过。第二个模块者:写一个模块的时候,会附带写一个简短的测试程序来测试这个方法。并且在未对刚写的方法做出确认(通过测试确认之前的方法和他所期望的结果一致)之前,是不会接着写新代码的。序言(2)两种不同的做法带来的两种不同的结果:第一个开发者:期限的前一天,集成演示时,一点输出都没有;利用调试器跟踪,经过长时间的琢磨,找到并纠正了这个bug,但是,同时又发现了其他好几个bug。结果,筋疲力尽,而且未能及时完成任务。第二个开发者:期限的前一天,集成代码到整个系统中,并且能够很好的运行;虽然在其中也出现了一个小问题,但是很对就发现了问题所在,并在几分钟之内就解决了这个问题。序言(3)不写测试的借口编写单元测试太花时间了运行测试的时间太长了测试代码并不是我的工作我并不清楚代码的行为,所以也就无从测试这些代码都能够编译通过公司请我来是为了写代码,而不是写测试如果我让测试员或者QA人员没有工作,那么我会觉得很内疚我的公司并不会让我在真实系统中运行单元测试单元测试什么是单元测试单元测试是开发者编写的一小段代码,用于检验被测代码的一个很小的、很明确的功能是否正确。通常而言,一个单元测试是用于判断某个特定条件(或者场景)下某个特定函数的行为。执行单元测试,是为了证明某段代码的行为确实和开发者所期望的一致为什么要使用单元测试单元测试不但会使你的工作完成的更轻松,而且会令你的设计变得更好,甚至大大减少你花在调试上面的时间。单元测试可以提高底层代码的正确性,从而提高调用它的高层代码的正确性。使用单元测试这个简单有效的技术就是为了令代码变得更加完美。目的与范围目的为了提高软件开发效率和质量统一单元测试风格保证文档与单元测试编码的一致性方便开发人员进行单元测试的开发使单元测试能够有效正常的自动执行范围单元测试属于软件模块开发过程中的活动提纲1.序言2.一个单元测试示例3.测试内容及方法4.边界条件5.单元测试工具6.Mock对象7.好的测试品质8.在项目中进行测试一个单元测试(1)简单的例子:查找list[]中的最大值:intLargest(intlist[],intlength);首份实现代码如下:intLargest(intlist[],intlength){inti,max;for(i=0;i(length–1);i++){if(list[i]max){max=list[i];}}returnmax;}一个单元测试(2)计划你的测试给定一个数组[7,8,9],这个方法返回9。这就构成了一个合理的测试。你能想出其他一些测试么?如果list中有两个相等的最大值,将会出现什么情况?[7,9,8,9]→9如果list中只有一个元素,结果会是怎么样的呢?[1]→1如果list所包含的是负数,结果又会怎么样呢?[-9,-8,-7]→-7一个单元测试(3)测试一个简单的方法编写测试代码TEST(CheckResult,Max_Int){intlist[]={7,8,9};CHECK(Largest(List,3)==9);}编译结果如下一个单元测试(4)源程序中被测试方法的错误查找与修改发现max值没初始化然后进行修改并且设置max的初始数值:max=0重新编译并运行测试测试运行结果如下:一个单元测试(5)再次进行源文件被测试方法的bug查找与修改为什么返回的最大值是8,好像程序根本没有考虑list中的最后一个元素似的。查看源文件,发现for循环结束得早了。修改:将for循环中ilength-1修改成为ilength编译源文件并运行该测试,程序将没有failure输出。一个单元测试(6)其他考虑到的测试方法的尝试存在重复的最大值的情况[9,7,9,8]只有一个元素的情况[1]全是负值的情况[-9,-8,-7]编译源文件并运行修改后的测试,发现重复最大值和只有一个元素的情况,测试都通过了。但是全是负值的情况出现了问题,如下:一个单元测试(7)第三次进行源文件被测试方法的bug查找与修改为什么返回的最大值是0,它是从哪里来的?看来用0来初始化max是个错误的做法我们应该用list[0]来作为max的初始值修改过后,便以并重新运行该测试,结果也通过了该测试。一个单元测试(8)是否说明获取数组最大值的方法已经完全没有问题了呢?如果数组为null,会出现什么情况?如果数组的长度为0,会出现什么情况?通常,我们会认为这是一个错误,将抛出一个异常,修改方法:intLargest(intlist[],intlength){inti,max;if(list==null||length==0){return0;}……}提纲1.序言2.一个单元测试示例3.测试内容及方法4.边界条件5.单元测试工具6.Mock对象7.好的测试品质8.在项目中进行测试测试内容单元测试的对象:软件设计的最小单位——模块或函数输入数据和形参的定义是否一致;是否修改了只做输入用的形式参数;全局变量的定义在各模块中是否一致;……模块接口出错处理独立路径边界条件局部数据结构局部变量类型是否正确是否初始化了错误的初始值或错误的默认值……运算是否正确逻辑是否正确是否会产生死循环、不可终止的迭代……对错误条件的处理不正确在对错误进行处理之前,错误条件已经引起系统的干预模块是否能恢复正常……在循环的第0次、1次、n次运算或判断中取最大最小值时输入参数的最大最小值……测试方法:Right-BICEP(1)6个值得测试的具体部位,他们能够提高你的测试技巧Right-结果是否正确?B-是否所有的边界条件都是正确的?I-能查一下反向关联吗?C-能用其他手段交叉检查一下结果吗?E-你是否可以强制错误条件发生?P-是否满足性能要求?测试方法:Right-BICEP(2)结果是否正确如果代码能够运行正确,我要怎么才知道他是正确的呢?至少需要确认代码所做的和你的期望是一致的。使用数据文件对于有大量测试数据的测试,考虑使用一个独立的数据文件来存储这些测试数据,然后单元测试读取该文件。对于验证被测方法是正确的这件事情,如果某些做法能够使它变得更加容易,那就采纳它吧。边界条件一个想到可能的边界条件的简单办法就是记住助记短语CORRECT。Conformance(一致性):值是否和预期的一致Ordering(顺序性):值是否如应该的那样,是有序或者无序的Range(区间性):值是否位于合理的最小值和最大值之间Reference(依赖性):代码是否引用了一些不在代码本身控制范围内的外部资源Existence(存在性):值是否存在(是否非null,非0,在一个集合中等)Cardinatity(基数性):是否恰好有足够的值Time(绝对或者相对的时间性):所有的事情的发生是否是有序的?是否是在正确的时刻?是否恰好及时?测试方法:Right-BICEP(3)检查反向关联对于某些方法,可以使用反向的逻辑关系来验证他们。用对结果进行平方的方式来检查一个计算平方根的方法,然后测试结果是否和原数据很接近为了检查某条记录是否成功插入了数据库,你可以通过查询这条记录来验证。使用其他手段来实现交叉检查计算一个量会存在一个以上的方法。可以利用另一个方法来交叉测试原方法的结果。使用类本身不同组成部分的数据来进行交叉检查。如图书馆的数据系统,可以通过借出数和库存数之和必定等于所藏书籍总量这种约束来进行检查。测试方法:Right-BICEP(4)强制产生错误条件真实世界中出现的错误:磁盘满,网络断等,可以利用Mock对象环境方面的约束的考虑:系统过载、内存耗光等性能特性要检查的是性能特性,而不是性能本身。性能特性有着“随着输入尺寸慢慢变大,问题慢慢变复杂”的趋势性能特性的快速回归测试由于测试时间较长,可以考虑每隔几天运行一次需要使用一些测试工具提纲1.序言2.一个单元测试示例3.测试内容及方法4.边界条件5.单元测试工具6.Mock对象7.好的测试品质8.在项目中进行测试CORRECT边界条件(1)边界条件一致性(Conformance):值是否符合预期的格式有序性(Ordering):一组值是该有序的,还是该无序的区间性(Range):值是否在一个合理的最大值和最小值的范围之内引用、耦合性(Reference):代码是否引用了一些不受代码本身直接控制的外部因素存在性(Existence):值是否存在(例如,非null,非零,包含于某个集合等)基数性(Cardinality):是否恰好有足够的值时间性(Time):所有事情是否都是按顺序发生的?是否在正确的时间?是否及时?CORRECT边界条件(2)一致性很多情况下,你所期望的或产生的数据必须符合某种特定的格式。例如Email地址:name@somewhere.com可能还会有一些附加的用点(.)隔开的部分:firstname.lastname@subdomain.somewhere.com可能还会有更少见的格式:firstname.lastname%somewhere@subdomain.somewhere.com再如一类报告数据,包括一个头部记录,这个头部记录链接到了一些数据记录,最后是尾部记录。需要测试多少情况?1.如果没有头部记录,只有数据记录和尾部记录,要怎样处理?2.如果没有数据记录,只有头部记录和尾部记录,要怎样处理?3.如果没有尾部记录,只有头部记录和数据记录,要怎样处理?4.如果只有一个尾部记录,要怎样处理?5.如果只有一个头部记录,要怎样处理?6.如果只有一个数据记录,要怎样处理?CORRECT边界条件(3)有序性有时需要考虑数据的顺序或者是一个很大的数据集合中某一数据的位置有时一个数据位于集合中的最前或者最后的时候,程序中的bug会暴露出来。这是有序性的一个方面,如查找最大值的方法有时需要对一系列数据集合按照某种预定的情况进行排序操作。这是有序性的另一个方面。例如餐馆的菜单的集合。还需要考虑一个数据集合已经排好序的情况或者已经反向排好序的情况。CORRECT边界条件(4)区间性对于一个变量,它所属类型的取值范围可能比你需要或想要得更加宽广。如我们通常用整形来表示一个人的岁数,但是显然没有人能够活到20000岁,尽管20000是一个合法的整型值。一个罗盘头指向的角度不可能大于360度等。几乎所有的索引概念都应该被大量的测试开始索引和结束索引有相同的值第一个索引值大于最后一个索引值索引值是负的索引值大于允许值Count不能匹配确切索引的个数……CORRECT边界条件(5)引用/耦合性程序引用了哪些位于程序之外的事物程序引用了哪些外部依赖类应该处于什么样的状态程序运行还需要存在哪些其他的条件一个已知方法的前条件:系统必须处于什么状态下该方法才能运行。一个已知方法的后条件:你的方法将会保证哪些状态发生CORRECT边界条件(6)存在性给定的事物存在吗?如果它为null如果它为空值如果它等于0其他与存在性相关的陷阱确认你的方法处理了“不存在”的情况CORRECT边界条件(7)基数性这里的基数指的就是计数(counting)“0-1-n”原则这是一个存在性相关的问题,但是你需要确信:你计算得到的数目和你所需要的数目是一致的。在大部分情况下,只须考虑下面三个问题:1.零2.一3.多于一针对基数性的测试
本文标题:软件单元测试方法
链接地址:https://www.777doc.com/doc-3564512 .html