软件单元测试方法精.ppt

上传人:石*** 文档编号:78782816 上传时间:2023-03-19 格式:PPT 页数:93 大小:8.19MB
返回 下载 相关 举报
软件单元测试方法精.ppt_第1页
第1页 / 共93页
软件单元测试方法精.ppt_第2页
第2页 / 共93页
点击查看更多>>
资源描述

《软件单元测试方法精.ppt》由会员分享,可在线阅读,更多相关《软件单元测试方法精.ppt(93页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、软件单元测试方法第1页,本讲稿共93页提纲提纲1.序言序言2.一个单元测试示例一个单元测试示例3.测试内容及方法测试内容及方法4.边界条件边界条件5.单元测试工具单元测试工具6.Mock对象对象7.好的测试品质好的测试品质8.在项目中进行测试在项目中进行测试第2页,本讲稿共93页序言(序言(1)要向客户演示系统的基本功能,且临近最终期限时,两个开发者的两种不同的做法:第一个开发者:每天着急地写代码,写完一个类又写一个类,写完一个方法又接着写两一个方法,有时不得不停下来做一些调整,使得代码能够编译通过。第二个模块者:写一个模块的时候,会附带写一个简短的测试程序来测试这个方法。并且在未对刚写的方法

2、做出确认(通过测试确认之前的方法和他所期望的结果一致)之前,是不会接着写新代码的。第3页,本讲稿共93页序言(序言(2)两种不同的做法带来的两种不同的结果:第一个开发者:期限的前一天,集成演示时,一点输出都没有;利用调试器跟踪,经过长时间的琢磨,找到并纠正了这个bug,但是,同时又发现了其他好几个bug。结果,筋疲力尽,而且未能及时完成任务。第二个开发者:期限的前一天,集成代码到整个系统中,并且能够很好的运行;虽然在其中也出现了一个小问题,但是很对就发现了问题所在,并在几分钟之内就解决了这个问题。第4页,本讲稿共93页序言(序言(3)不写测试的借口编写单元测试太花时间了运行测试的时间太长了测试

3、代码并不是我的工作我并不清楚代码的行为,所以也就无从测试这些代码都能够编译通过公司请我来是为了写代码,而不是写测试如果我让测试员或者QA人员没有工作,那么我会觉得很内疚我的公司并不会让我在真实系统中运行单元测试第5页,本讲稿共93页单元测试单元测试什么是单元测试单元测试是开发者编写的一小段代码,用于检验被测代码的一个很小的、很明确的功能是否正确。通常而言,一个单元测试是用于判断某个特定条件(或者场景)下某个特定函数的行为。执行单元测试,是为了证明某段代码的行为确实和开发者所期望的一致为什么要使用单元测试单元测试不但会使你的工作完成的更轻松,而且会令你的设计变得更好,甚至大大减少你花在调试上面的

4、时间。单元测试可以提高底层代码的正确性,从而提高调用它的高层代码的正确性。使用单元测试这个简单有效的技术就是为了令代码变得更加完美。第6页,本讲稿共93页目的与范围目的与范围目的目的为了提高软件开发效率和质量 统一单元测试风格 保证文档与单元测试编码的一致性 方便开发人员进行单元测试的开发 使单元测试能够有效正常的自动执行 范围范围单元测试属于软件模块开发过程中的活动第7页,本讲稿共93页提纲提纲1.序言序言2.一个单元测试示例一个单元测试示例3.测试内容及方法测试内容及方法4.边界条件边界条件5.单元测试工具单元测试工具6.Mock对象对象7.好的测试品质好的测试品质8.在项目中进行测试在项

5、目中进行测试第8页,本讲稿共93页一个单元测试(一个单元测试(1)简单的例子:查找list中的最大值:int Largest(int list,int length);首份实现代码如下:int Largest(int list,int length)int i,max;for(i=0;i max)max=listi;return max;第9页,本讲稿共93页一个单元测试(一个单元测试(2)计划你的测试给定一个数组7,8,9,这个方法返回9。这就构成了一个合理的测试。你能想出其他一些测试么?l如果list中有两个相等的最大值,将会出现什么情况?7,9,8,9 9l如果list中只有一个元素,结

6、果会是怎么样的呢?1 1l如果list所包含的是负数,结果又会怎么样呢?-9,-8,-7 -7第10页,本讲稿共93页一个单元测试(一个单元测试(3)测试一个简单的方法编写测试代码TEST(CheckResult,Max_Int)int list=7,8,9;CHECK(Largest(List,3)=9);编译结果如下第11页,本讲稿共93页一个单元测试(一个单元测试(4)源程序中被测试方法的错误查找与修改发现max值没初始化然后进行修改并且设置max的初始数值:max=0重新编译并运行测试测试运行结果如下:第12页,本讲稿共93页一个单元测试(一个单元测试(5)再次进行源文件被测试方法的b

7、ug查找与修改为什么返回的最大值是8,好像程序根本没有考虑list中的最后一个元素似的。查看源文件,发现for循环结束得早了。修改:将for循环中i length-1修改成为i length编译源文件并运行该测试,程序将没有failure输出。第13页,本讲稿共93页一个单元测试(一个单元测试(6)其他考虑到的测试方法的尝试存在重复的最大值的情况 9,7,9,8只有一个元素的情况 1全是负值的情况-9,-8,-7编译源文件并运行修改后的测试,发现重复最大值和只有一个元素的情况,测试都通过了。但是全是负值的情况出现了问题,如下:第14页,本讲稿共93页一个单元测试(一个单元测试(7)第三次进行源

8、文件被测试方法的bug查找与修改为什么返回的最大值是0,它是从哪里来的?看来用0来初始化max是个错误的做法我们应该用list0来作为max的初始值修改过后,便以并重新运行该测试,结果也通过了该测试。第15页,本讲稿共93页一个单元测试(一个单元测试(8)是否说明获取数组最大值的方法已经完全没有问题了呢?如果数组为null,会出现什么情况?如果数组的长度为0,会出现什么情况?通常,我们会认为这是一个错误,将抛出一个异常,修改方法:int Largest(int list,int length)int i,max;if(list=null|length=0)return 0;第16页,本讲稿共9

9、3页提纲提纲1.序言序言2.一个单元测试示例一个单元测试示例3.测试内容及方法测试内容及方法4.边界条件边界条件5.单元测试工具单元测试工具6.Mock对象对象7.好的测试品质好的测试品质8.在项目中进行测试在项目中进行测试第17页,本讲稿共93页测试内容测试内容单元测试的对象:软件设计的最小单位模块或函数输入数据和形参的定义是否输入数据和形参的定义是否一致;一致;是否修改了只做输入用的是否修改了只做输入用的形式参数;形式参数;全局变量的定义在各模块中全局变量的定义在各模块中是否一致;是否一致;模块接口模块接口出错处理出错处理独立路径独立路径边界条件边界条件局部数据结构局部数据结构局部变量类型

10、是否正确局部变量类型是否正确是否初始化了是否初始化了错误的初始值或错误的错误的初始值或错误的默认值默认值运算是否正确运算是否正确逻辑是否正确逻辑是否正确是否会产生死循环、不可是否会产生死循环、不可终止的迭代终止的迭代对错误条件的处理不正确对错误条件的处理不正确在对错误进行处理之前,在对错误进行处理之前,错误条件已经引起系统的错误条件已经引起系统的干预干预模块是否能恢复正常模块是否能恢复正常在循环的第在循环的第0次、次、1次、次、n次次运算或判断中取最大最小值时运算或判断中取最大最小值时输入参数的最大最小值输入参数的最大最小值第18页,本讲稿共93页测试方法:测试方法:Right-BICEP(1

11、)6个值得测试的具体部位,他们能够提高你的测试技巧Right结果是否正确?B是否所有的边界条件都是正确的?I能查一下反向关联吗?C能用其他手段交叉检查一下结果吗?E你是否可以强制错误条件发生?P是否满足性能要求?第19页,本讲稿共93页测试方法:测试方法:Right-BICEP(2)结果是否正确如果代码能够运行正确,我要怎么才知道他是正确的呢?如果代码能够运行正确,我要怎么才知道他是正确的呢?至少需要确认代码所做的和你的期望是一致的。使用数据文件使用数据文件对于有大量测试数据的测试,考虑使用一个独立的数据文件来存储这些测试数据,然后单元测试读取该文件。对于验证被测方法是正确的这件事情,如果某些

12、做法能够使它变得更加容易,那就采纳它吧。边界条件一个想到可能的边界条件的简单办法就是记住助记短语一个想到可能的边界条件的简单办法就是记住助记短语CORRECT。Conformance(一致性):值是否和预期的一致Ordering(顺序性):值是否如应该的那样,是有序或者无序的Range(区间性):值是否位于合理的最小值和最大值之间Reference(依赖性):代码是否引用了一些不在代码本身控制范围内的外部资源Existence(存在性):值是否存在(是否非null,非0,在一个集合中等)Cardinatity(基数性):是否恰好有足够的值Time(绝对或者相对的时间性):所有的事情的发生是否是

13、有序的?是否是在正确的时刻?是否恰好及时?第20页,本讲稿共93页测试方法:测试方法:Right-BICEP(3)检查反向关联对于某些方法,可以使用反向的逻辑关系来验证他们。用对结果进行平方的方式来检查一个计算平方根的方法,然后测试结果是否和原数据很接近为了检查某条记录是否成功插入了数据库,你可以通过查询这条记录来验证。使用其他手段来实现交叉检查计算一个量会存在一个以上的方法。可以利用另一个方法来交叉测试原方法的结果。使用类本身不同组成部分的数据来进行交叉检查。如图书馆的数据系统,可以通过借出数和库存数之和必定等于所藏书籍总量这种约束来进行检查。第21页,本讲稿共93页测试方法:测试方法:Ri

14、ght-BICEP(4)强制产生错误条件真实世界中出现的错误:磁盘满,网络断等,可以利用Mock对象环境方面的约束的考虑:系统过载、内存耗光等性能特性要检查的是性能特性,而不是性能本身。性能特性有着“随着输入尺寸慢慢变大,问题慢慢变复杂”的趋势性能特性的快速回归测试由于测试时间较长,可以考虑每隔几天运行一次需要使用一些测试工具第22页,本讲稿共93页提纲提纲1.序言序言2.一个单元测试示例一个单元测试示例3.测试内容及方法测试内容及方法4.边界条件边界条件5.单元测试工具单元测试工具6.Mock对象对象7.好的测试品质好的测试品质8.在项目中进行测试在项目中进行测试第23页,本讲稿共93页CO

15、RRECT边界条件(边界条件(1)边界条件一致性(Conformance):值是否符合预期的格式有序性(Ordering):一组值是该有序的,还是该无序的区间性(Range):值是否在一个合理的最大值和最小值的范围之内引用、耦合性(Reference):代码是否引用了一些不受代码本身直接控制的外部因素存在性(Existence):值是否存在(例如,非null,非零,包含于某个集合等)基数性(Cardinality):是否恰好有足够的值时间性(Time):所有事情是否都是按顺序发生的?是否在正确的时间?是否及时?第24页,本讲稿共93页CORRECT边界条件(边界条件(2)一致性很多情况下,你所

16、期望的或产生的数据必须符合某种特定的格式。很多情况下,你所期望的或产生的数据必须符合某种特定的格式。例如例如Email地址:地址:可能还会有一些附加的用点(.)隔开的部分:可能还会有更少见的格式:firstname.lastname%再如一类报告数据,包括一个头部记录,这个头部记录链接到了一些数据记录,最后再如一类报告数据,包括一个头部记录,这个头部记录链接到了一些数据记录,最后是尾部记录。需要测试多少情况?是尾部记录。需要测试多少情况?1.如果没有头部记录,只有数据记录和尾部记录,要怎样处理?2.如果没有数据记录,只有头部记录和尾部记录,要怎样处理?3.如果没有尾部记录,只有头部记录和数据记

17、录,要怎样处理?4.如果只有一个尾部记录,要怎样处理?5.如果只有一个头部记录,要怎样处理?6.如果只有一个数据记录,要怎样处理?第25页,本讲稿共93页CORRECT边界条件(边界条件(3)有序性有时需要考虑数据的顺序或者是一个很大的数据集合中某一数据的位置有时一个数据位于集合中的最前或者最后的时候,程序中的bug会暴露出来。这是有序性的一个方面,如查找最大值的方法有时需要对一系列数据集合按照某种预定的情况进行排序操作。这是有序性的另一个方面。例如餐馆的菜单的集合。还需要考虑一个数据集合已经排好序的情况或者已经反向排好序的情况。第26页,本讲稿共93页CORRECT边界条件(边界条件(4)区

18、间性对于一个变量,它所属类型的取值范围可能比你需要或想要对于一个变量,它所属类型的取值范围可能比你需要或想要得更加宽广。得更加宽广。如我们通常用整形来表示一个人的岁数,但是显然没有人能如我们通常用整形来表示一个人的岁数,但是显然没有人能够活到够活到20000岁,尽管岁,尽管20000是一个合法的整型值。是一个合法的整型值。一个罗盘头指向的角度不可能大于一个罗盘头指向的角度不可能大于360度等。度等。几乎所有的索引概念都应该被大量的测试几乎所有的索引概念都应该被大量的测试开始索引和结束索引有相同的值第一个索引值大于最后一个索引值索引值是负的索引值大于允许值Count不能匹配确切索引的个数第27页

19、,本讲稿共93页CORRECT边界条件(边界条件(5)引用/耦合性程序引用了哪些位于程序之外的事物程序引用了哪些外部依赖类应该处于什么样的状态程序运行还需要存在哪些其他的条件一个已知方法的前条件:系统必须处于什么状态下该方法才能运行。一个已知方法的后条件:你的方法将会保证哪些状态发生第28页,本讲稿共93页CORRECT边界条件(边界条件(6)存在性给定的事物存在吗?如果它为null如果它为空值如果它等于0其他与存在性相关的陷阱确认你的方法处理了“不存在”的情况第29页,本讲稿共93页CORRECT边界条件(边界条件(7)基数性这里的基数指的就是计数(这里的基数指的就是计数(countingc

20、ounting)“0-1-n”原则原则这是一个存在性相关的问题,但是你需要确信:你计算得到的数目和你所需要的数目是一致的。在大部分情况下,只须考虑下面三个问题:1.零 2.一 3.多于一针对基数性的测试主要考虑:是否具有两个或者多个测试对象。在某些情况下,具体数针对基数性的测试主要考虑:是否具有两个或者多个测试对象。在某些情况下,具体数目的不同可能也会引入一些差异。目的不同可能也会引入一些差异。一个网店系统,当老板要求实时将客户预定的前十个产品的条目发送到老板的PDA上时,你需要测试哪些内容?列表条目不足十个,列表为空,产品本身就没有十个等等,所有这些情况下,能出报表么?突然过了三天老板需要前

21、20个产品的条目,怎么办?过了一周后老板又马上只要前5个产品的条目,怎么解决?正确答案是“一行代码”,类似下面的#define NUMBER_TO_RETAIN=20;第30页,本讲稿共93页CORRECT边界条件(边界条件(8)时间性需要始终记得以下这些与时间相关的方面需要始终记得以下这些与时间相关的方面:相对时间(时间上的顺序)绝对时间(消耗的时间和钟表上的时间)并发问题问题问题:一年中的每一天都是24小时吗?答案:“要看情况”。在UTC(Universal Coordinated Time,Greenwich Mean Time即GMT的现代版)中,答案是“正确”;在不遵守DST(Day

22、light Savings Time)的地方,答案是“正确”;而在美国的大部分地区(),答案是“错误”。四月,会遇到23小时的一天;十月,会遇到25小时的一天。不要期望底层库会替你正确处理这些问题。不幸的是,底层库遇到时间问题,很多代码会出问题。第31页,本讲稿共93页CORRECT边界条件(边界条件(9)问题在前面的例子中我们使用了哪些边界条件?第32页,本讲稿共93页提纲提纲1.序言序言2.一个单元测试示例一个单元测试示例3.测试内容及方法测试内容及方法4.边界条件边界条件5.单元测试工具单元测试工具6.Mock对象对象7.好的测试品质好的测试品质8.在项目中进行测试在项目中进行测试第33

23、页,本讲稿共93页单元测试工具单元测试工具针对C/C+开源xUnit框架CppUnit :JUnit移植而来CppUnitLite:CppUnit的轻量级版本Google Test:功能强大Unity :C语言cMockery :C语言,集成Mock功能第34页,本讲稿共93页CppUnitLite(1)文件目录.om CppUnitLite Failure.cpp Failure.h .CppUnitTests Cpp StackMain.cpp StackTest.cpp Stack.h readme.txt核心代码核心代码主程序主程序测试测试代码代码第35页,本讲稿共93页CppUnit

24、Lite(2)使用VC 2008新建工程第36页,本讲稿共93页CppUnitLite(3)导入文件CppUintLite的源代码测试代码第37页,本讲稿共93页CppUnitLite(4)设置路径第38页,本讲稿共93页CppUnitLite(5)主函数修改int main()TestResult tr;TestRegistry:runAllTests(tr);getch();return 0;第39页,本讲稿共93页CppUnitLite(6)被测函数int Add(int Num1,int Num2)return(Num1+Num2);编写测试代码TEST(CheckResult,Add

25、)CHECK(Add(0 x1,0 x2)=0 x3);第40页,本讲稿共93页CppUnitLite(7)运行编译结果第41页,本讲稿共93页CppUnitLite(8)编写测试代码TEST(CheckResult,Add)CHECK(0 x3=Add(0 x1,0 x2);CHECK(0 x3=Add(0 x2,0 x2);第42页,本讲稿共93页Google Test的安装(的安装(1)下载源代码http:/ 编译生成Lib文件使用VC 2008编译msvc目录下的工程,生成gtestd.lib第43页,本讲稿共93页Google Test的安装(的安装(2)设置gtest头文件路径第4

26、4页,本讲稿共93页Google Test的安装(的安装(3)设置gtest.lib路径第45页,本讲稿共93页Google Test的安装(的安装(4)Runtime Library设置第46页,本讲稿共93页Google Test的使用(的使用(1)主函数的修改void _tmain(int argc,_TCHAR*argv)testing:InitGoogleTest(&argc,argv);RUN_ALL_TESTS();getch();return;第47页,本讲稿共93页Google Test的使用(的使用(2)被测函数int Add(int Num1,int Num2)retur

27、n(Num1+Num2);测试代码TEST(AddTest,HandleNoneZeroInput)EXPECT_EQ(3,Add(1,2);第48页,本讲稿共93页Google Test的使用(的使用(3)编译结果第49页,本讲稿共93页Google Test的使用(的使用(4)测试代码TEST(AddTest,HandleNoneZeroInput)EXPECT_EQ(3,Add(1,2);EXPECT_EQ(3,Add(2,2);第50页,本讲稿共93页Google Test的使用(的使用(5)两类断言ASSERT_*系列系列当检查点失败时,退出当前函数。EXPECT_*系列系列当检查点

28、失败时,继续往下执行。第51页,本讲稿共93页Google Test的使用(的使用(6)检查的种类布尔值检查数值型数据检查字符串检查显示返回成功或失败异常检查浮点型检查类型检查第52页,本讲稿共93页Google Test的使用(的使用(7)Fatal assertion Nonfatal assertion Verifies ASSERT_EQ(expected,actual);EXPECT_EQ(expected,actual);expected=actual ASSERT_NE(val1,val2);EXPECT_NE(val1,val2);val1!=val2 ASSERT_LT(va

29、l1,val2);EXPECT_LT(val1,val2);val1 val2 ASSERT_LE(val1,val2);EXPECT_LE(val1,val2);val1 val2 ASSERT_GE(val1,val2);EXPECT_GE(val1,val2);val1=val2 数值型数据检查第53页,本讲稿共93页Google Test的参数化(的参数化(1)需要测试多组数据时TEST(IsPrimeTest,HandleTrueReturn)EXPECT_EQ(4,Add(1,3);EXPECT_EQ(5,Add(2,3);EXPECT_EQ(6,Add(3,3);EXPECT_E

30、Q(7,Add(4,3);EXPECT_EQ(8,Add(5,3);第54页,本讲稿共93页Google Test的参数化(的参数化(2)参数化class IsPrimeParamTest:public:testing:TestWithParam;INSTANTIATE_TEST_CASE_P(TrueReturn,IsPrimeParamTest,testing:Values(1,2,3,4,5);TEST_P(IsPrimeParamTest,HandleTrueReturn)int n=GetParam();EXPECT_EQ(n+3,Add(n,3);第55页,本讲稿共93页参数生成器

31、Google Test的参数化(的参数化(3)Range(begin,end,step)范围在beginend之间,步长为step,不包括endValues(v1,v2,.,vN)v1,v2到vN的值ValuesIn(container)ValuesIn(begin,end)从一个C类型的数组或是STL容器,或是迭代器中取值Bool()取false 和 true 两个值 Combine(g1,g2,.,gN)将g1,g2,.gN进行排列组合,g1,g2,.gN本身是一个参数生成器,每次分别从g1,g2,.gN中各取出一个值,组合成一个元组(Tuple)作为一个参数。第56页,本讲稿共93页Go

32、ogle Test的参数化(的参数化(4)运行结果第57页,本讲稿共93页Google Test的死亡测试(的死亡测试(1)死亡测试通常在测试过程中,我们需要考虑各种各样的输入,有的输入可能直接导致程序崩溃,这时我们就需要检查程序是否按照预期的方式挂掉,这也就是所谓的“死亡测试”。Google Test的死亡测试能做到在一个安全的环境下执行崩溃的测试案例,同时又对崩溃结果进行验证。宏定义ASSERT_DEATH(statement,regex);EXPECT_DEATH(statement,regex);statement crashes with the given error ASSERT

33、_EXIT(statement,predicate,regex);EXPECT_EXIT(statement,predicate,regex);statement exits with the given error and its exit code matches predicate第58页,本讲稿共93页Google Test的死亡测试(的死亡测试(2)示例int Div(int Num1,int Num2)return Num1/Num2;TEST(DivDeathTest,Demo)EXPECT_DEATH(Add(1,0),);第59页,本讲稿共93页Google Test的死亡测

34、试(的死亡测试(3)运行结果第60页,本讲稿共93页Unity(1)C语言2个文件unity.cunity.h可以用TC、GCC、STD等编译,并下载到板卡运行第61页,本讲稿共93页Unity(1)主程序int main(void)Unity.TestFile=main.c;UnityBegin();RUN_TEST(test_Add);/*添加测试函数*/UnityEnd();getch();return 0;第62页,本讲稿共93页Unity(3)被测函数int Add(int Num1,int Num2)return(Num1+Num2);测试代码void test_Add(void)

35、TEST_ASSERT_EQUAL(3,Add(1,2);第63页,本讲稿共93页Unity(4)编译运行结果第64页,本讲稿共93页单元测试工具总结单元测试工具总结优点自动化高效率容易进行回归测试案例库(测试用例)不断丰富第65页,本讲稿共93页提纲提纲1.序言序言2.一个单元测试示例一个单元测试示例3.测试内容及方法测试内容及方法4.边界条件边界条件5.单元测试工具单元测试工具6.Mock对象对象7.好的测试品质好的测试品质8.在项目中进行测试在项目中进行测试第66页,本讲稿共93页Mock对象(对象(1)设计了一个定时器,每天下午17:00时产生报警。测试时,是否真要等待到17:00?第

36、67页,本讲稿共93页Mock对象(对象(2)示例:调用getTime()来返回系统当前的日期和时间int Alarm()int i=getTime();/读取时钟芯片 if(17=i)Sound();/发出报警声 return 1;else return 0;第68页,本讲稿共93页Mock对象(对象(3)在进行测试时,可能需要的时间并非是系统当前的时间,怎么办?我们可以如下替换:int getTime()if(debug)return debug_cur_time;else/读取时钟芯片上面的方法是替换的真正功能的手段之一,但有些凌乱第69页,本讲稿共93页Mock对象(对象(3)Mock

37、对象Mock对象可以帮助我们解决之前的替换功能。对象可以帮助我们解决之前的替换功能。Mock对象是真实对象在调试器的替代品。对象是真实对象在调试器的替代品。系统中真实对象的一些情况:系统中真实对象的一些情况:真实对象具有不确定的行为(产生不可预料的结果,如股票行情)真实对象很难被创建真实对象的某些行为很难触发(如网络错误)真实对象令程序的运行速度很慢真实对象有(或者是)用户界面测试需要询问真实对象他是如何被调用的真实对象实际上并不存在(当需要和其他开发小组,或者新的硬件系统打交道的时候,这是一个普遍问题)第70页,本讲稿共93页Mock对象(对象(4)借助于Mock对象,我们可以解决上面提到的

38、所有问题,使用Mock对象的三个关键步骤:使用一个接口来描述这个对象为产品代码实现这个接口以测试为目的,在Mock对象中实现这个接口因为被测试代码只会通过接口来引用对象,所以他完全可以不知道他引用的究竟是真实对象还是Mock对象第71页,本讲稿共93页cMockery(1)Google在2008年9月15日公开C单元测试的一个轻量级的框架免费且开源,google提供技术支持 轻量级的框架,使测试更加快速简单;避免使用复杂的编译器特性,对老版本的编译器来讲,兼容性好并不强制要求待测代码必须依赖C99标准,这一特性对许多嵌入式系统的开发很有用第72页,本讲稿共93页cMockery(2)C语言2个

39、文件cmockery.ccmockery.h可以用GCC等编译,并下载到板卡运行第73页,本讲稿共93页cMockery(3)模拟接口int getTime(void)return mock();测试代码void test_Alarm_succ(void*state)will_return(getTime,18);assert_true(Alarm()=0);void test_Alarm_fail(void*state)will_return(getTime,17);assert_true(Alarm()=1);第74页,本讲稿共93页cMockery(4)主函数void main()con

40、st UnitTest tests=unit_test(test_Alarm_succ),unit_test(test_Alarm_fail),;run_tests(tests);getch();第75页,本讲稿共93页cMockery(5)编译运行第76页,本讲稿共93页cMockery(6)分配一块内存,用来存储你在will_return中设定的返回值,用函数名字符串做索引;在mock()中则通过调用mock的函数的名字去匹配,得到已经设定好的存储在堆内存上的那个值,并返回;使被测试代码并不知道测试环境和真实环境之间的区别,因为它们都实现了相同的接口;这样,我们就可以借助Mock对象,通过

41、把时间设置为已知值,进而编写测试;所有这些,就是Mock对象的全部:伪装出真实世界的某些部分,使你可以集中精力测试好自己编写的代码。第77页,本讲稿共93页提纲提纲1.序言序言2.一个单元测试示例一个单元测试示例3.测试内容及方法测试内容及方法4.边界条件边界条件5.单元测试工具单元测试工具6.Mock对象对象7.好的测试品质好的测试品质8.在项目中进行测试在项目中进行测试第78页,本讲稿共93页好的测试品质(好的测试品质(1)好的测试应该具有以下品质,合称为A-TRIP自动化(Automatic)彻底的(Thorough)可重复的(Repeatable)独立的(Independent)专业的

42、(Professional)第79页,本讲稿共93页好的测试品质(好的测试品质(2)自动化调用测试自动化调用测试自动化调用一个或多个单元测试对你而言必须是非常容易的维护这个环境最重要的在于:不要引入一个由于需要手动步骤而打破这个自动化模型的测试。确保任何代码的签入都不会损坏位于任何机器的任何测试的机制能够持续构建和测试检查结果自动化检查结果自动化测试必须能够自己决定它是通过了还是失败了。一致性回归的一个重要特征就是让测试能够检查自身。第80页,本讲稿共93页好的测试品质(好的测试品质(3)彻底的他们测试了所有可能会出问题的情况他们测试了所有可能会出问题的情况一个极端:对于每行代码、代码可能达到

43、的每个分支、每个可能抛出的异常等等,都可以作为测试的对象。另一个极端:你仅仅测试最可能的情况边界条件、残缺和畸形的数据等等。Bug并不是均匀分布在原代码之中的,它们更倾向于扎堆于并不是均匀分布在原代码之中的,它们更倾向于扎堆于一块问题区域之中。一块问题区域之中。第81页,本讲稿共93页好的测试品质(好的测试品质(4)代码覆盖 路径覆盖第82页,本讲稿共93页好的测试品质(好的测试品质(5)可重复测试应该能够以任意的顺序一次又一次的运行,并且产生相同的结果。每个测试应当每次产生相同的结果。如果没有,那么它应当告诉你代码中存在有真正的bug。独立的测试应该是简洁而且精炼的,这意味着每个测试都应该有

44、很强的针对性,并且独立于环境和其他的测试。编写测试时,确保你一次只测试了一样东西。使用每个测试都有的setup和teardown以及每个类的setup和teardown来确保每个测试获得一个全新的开始。第83页,本讲稿共93页好的测试品质(好的测试品质(6)专业的必须使用和产品代码相同的专业水准来编写和维护测试代码。测试代码必须以同产品代码相同的风格来编写。测试必须是完整的意料中的结果是编写的测试代码至少和产品代码一样多。第84页,本讲稿共93页好的测试品质(好的测试品质(7)对测试进行测试如下理解:如下理解:源代码测试代码:对源代码进行测试的代码二重测试:对测试代码进行测试的测试代码三重测试

45、:对二重测试代码进行测试的测试代码上述理解将测试无休止的进行下去,何时才能终止呢上述理解将测试无休止的进行下去,何时才能终止呢?我们不需要做的那么极端,有两件事情可以帮助我们确保测试代码是正确的我们不需要做的那么极端,有两件事情可以帮助我们确保测试代码是正确的:在修整bug的同时改进测试通过引入bug来证明测试.如何修正如何修正Bug?如下四个简单步骤如下四个简单步骤:验明bug编写一个将失败的测试来证明bug的存在修正代码,让测试通过验证所有的测试仍然可以通过(也就是你没有在修补的时候损坏其他的测试)相同的问题还会在其他地方发生吗?相同的问题还会在其他地方发生吗?这就要求你把所学到的教训应用

46、到整个项目中去.第85页,本讲稿共93页提纲提纲1.序言序言2.一个单元测试示例一个单元测试示例3.测试内容及方法测试内容及方法4.边界条件边界条件5.单元测试工具单元测试工具6.Mock对象对象7.好的测试品质好的测试品质8.在项目中进行测试在项目中进行测试第86页,本讲稿共93页在项目中进行测试(在项目中进行测试(1)将测试的代码放入工程目录同一目录源文件:./prj/main.c测试文件:./prj/mainTest.cpp子目录:源文件:./prj/main.c测试文件:./prj/test/mainTest.cpp并行树:源文件:./prj/main.c测试文件:./test/mai

47、nTest.cpp不论使用哪种方法,都要保证在团队内能够得到一致的保持。第87页,本讲稿共93页在项目中进行测试(在项目中进行测试(2)测试的礼貌独立测试和与其他人一起测试的最大区别在于使工作中的测试和代码同步。在协同开发环境中,你应当在你签入代码的时候,确保这些代码已经有了一套完整的单元测试,并且所有的测试都能够通过。所有的测试应该在任何时刻都能通过。第88页,本讲稿共93页在项目中进行测试(在项目中进行测试(3)测试的频率如下情况下都必须进行测试如下情况下都必须进行测试编写了新的函数、模块、方法修正bug每次成功编译之后每次对版本控制的签入持续不断地第89页,本讲稿共93页在项目中进行测试

48、(在项目中进行测试(4)测试与遗留代码前提:系统已经有了大量的代码,而这些代码没有进行过单前提:系统已经有了大量的代码,而这些代码没有进行过单元测试元测试对于新写的代码,你显然应该同时编写单元测试。对于已经存在的代码,你可以选择为可测试的一切代码系统添加大量的单元测试;当然最好是只给最有可能出问题的代码添加测试。在这种环境中,单元测试的一个最重要的作用就是防止倒退:避免维护性的更正和修缮导致现存特性产生bug。第90页,本讲稿共93页在项目中进行测试(在项目中进行测试(5)测试与评审在编写产品代码之前,同时编写和评审测试。在编写产品代码之前,同时编写和评审测试。编码和评审以这样的顺序进行编码和评审以这样的顺序进行:编写test case和/或测试代码评审test case和/或测试代码经评审修改test case和/或测试代码编写能通过所有测试的产品代码评审产品代码和测试代码在每次评审后,修改测试代码和产品代码第91页,本讲稿共93页结束语结束语工作进展软件开发流程已有单元测试控制程序嵌入式软件方面已经起草了嵌入式软件单元测试指导书调研了数款单元测试工具准备在部分项目中试用为提高代码质量、产品可靠性而努力!第92页,本讲稿共93页谢谢!第93页,本讲稿共93页

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 大学资料

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁