您好,欢迎访问三七文档
单元测试快速的编程反馈软件开发的困难软件总是要修改的1.添加新特性2.Fixbug3.优化4.重构软件开发的困难修改软件是危险的举动1.我们如何得知已经正确的完成了修改?2.我们如何得知没有破坏任何(既有的)东西?软件开发的困难当前我们如何测试修改1.编译2.启动服务器3.启动一个以上的客户端4.鼠标操作5.看看效果6.重复这些步骤软件开发的困难这种测试的缺点1.不能立即获得反馈2.时间漫长3.运行次数不足4.甚至不测试软件开发的困难这种测试的外号编辑并祈祷单元测试概念1.由一组独立的测试构成,其中每个测试针对软件中的一个单独的原子行为单元2.并非检查一簇类是否能够合作良好,而是检查单个的对象行为是否正确单元测试传说中的例子,被测试的对象非常独立TEST(TestAdd){Mathmath;intresult=math.Add(11,12);CHECK_EQUAL(23,result);}单元测试传说中的过程1.实例化被测试对象2.提供测试数据3.调用被测试的方法4.验证测试结果单元测试实际情况1内存访问异常,ItemMngS无法在测试中实例化TEST(TestItemMng){CItemMngSmng;}单元测试实际情况2内存访问异常,无法调用被测试的方法TEST(TestBehit){CServerChaPlayerplayer;CServerChaPlayertarget;target.Behit(player);}单元测试实际情况3函数没有返回值,不知道如何验证结果TEST(TestAddInvite){CGroupUnitSunit;CServerChaPlayerplayer1,player2;unit.AddInvite(&player1,&player2);//howtocheck?}单元测试实际的情况1.理想是美好的,世界是残酷的2.软件由对象的相互协作来实现功能,对象之间充斥着必不可少的依赖3.软件的运行依赖于数据库,网络和文件系统4.多数函数的并没有返回值来验证行为单元测试比如1.CServerCha依赖各种CXXMng2.CXXMng之间相互依赖3.Auto_PlayerData是数据库的接口单元测试依赖的坏处1.无法将某个类从软件中隔离出来2.无法轻易的安置单元测试单元测试不经意的转变成集成测试1.我们可以将被依赖的类在测试中实例化2.被依赖的类肯定也在依赖别的类3.一环扣一环,于是我们把整个软件的大部分类都牵扯到一次测试中4.这个单元测试变得笨重5.这已经不是单元测试了!!!解依赖有依赖,就要解依赖在被测试的代码中,依赖是少量的解依赖就是将无法放入测试中的小段代码从整块代码中分离出来的行为解依赖就是构造接缝的过程解依赖什么是接缝?1.接缝是指程序中的一些特殊的点,在这些点上你无需作任何修改就可以达到改动程序的目的2.如果能够将接缝处的行为取代掉,我们就等于有选择的排除了某些依赖3.我们还可以将被依赖方替换为其他代码,以此感知测试代码对被依赖方的要求和影响解依赖其实接缝就是间接层接缝的基本类型1.虚函数2.指针:函数指针,全局变量,参数解依赖虚函数虚函数是接缝的根本在不改变软件的前提下,虚函数的行为可以在测试中的被派生类所改变解依赖code解依赖伪对象1.由于虚函数的存在,在测试中的派生类可以改变原来的行为2.在测试中用于伪装成被测试类的合作者的对象,称为伪对象3.伪对象是后面介绍的解依赖技术的根本解依赖全局变量实例化的全局对象是恶劣的,如:CPlayerMngg_playerMng;隐性初始化的单件是恶劣的,如:CCommonTimerMng::Instance();对象指针是一个接缝,可以在测试中替换指针实际指向的对象改变对象的行为需要虚函数解依赖code解依赖函数指针全局函数是不可替换的,如:G_GetPlayerUnit但是函数指针可以在测试中替换为其他签名相同的函数解依赖code解依赖参数指针参数对象指针和全局对象指针一样,可以在测试中替换实际指向的对象行为的改变依赖于虚函数解依赖code解依赖完全没有找到接缝,怎么办?没有接缝就创造接缝解依赖创建接缝的方法1.提取并重写调用2.设置并替换3.提取并重写获取方法4.提取并重写工厂方法解依赖提取并重写调用1.被测试的代码中,委托了其他的对象做某件事情2.给被测试对象新添加一个虚函数,封装这个委托3.在测试中用派生类覆盖这个虚函数解依赖code解依赖设置并替换1.对被依赖的对象或者单件提供一个设置方法2.在测试中,用设置方法改变他们解依赖code解依赖提取并重写获取方法1.在被测试的代码中,委托了其他对象做某件事情2.给被测试类添加一个获取委托对象的虚函数3.在测试中用派生类覆盖这个虚函数解依赖code解依赖提取并重写工厂方法1.构造函数包含太多依赖,以至于无法实例化被测试的类2.将依赖的代码提取到一个虚函数中3.在测试中覆盖该虚函数解依赖code解依赖创建接缝的更高级的方法1.参数包装器2.方法对象解依赖参数包装器1.有些类是无法修改的,final的2.有些类几乎无法实例化,解依赖也很费劲3.对这样的类,总是可以用wrapper将它包起来4.将实际代码中对该类的依赖换为对wrapper的依赖5.Wrapper有一套抽象的接口解依赖code解依赖方法对象1.有一些类十分巨大2.被测试的方法又臭又长3.创建一个新类,该类只有一个方法4.将被测试的代码放到新类的唯一方法中解依赖code解依赖总而言之,解依赖不是使用其中的某项技术,而是这些技术的综合运用虚函数是必须的解依赖是可以做到的解依赖是一种手术,手术可能会留下疤痕,但是可以治愈疾病接下来解依赖之后,也许就可以像传说中那样编写测试了真实的单元测试中,被测试类总是要在测试中被派生的,而且少不了其他伪对象的协助接下来code如何开始当前的项目完全没有单元测试动手吧,但不要试图一下子为所有的代码都建立单元测试蚕食,每次要进行修改,都试试将修改的部分放到测试下就好像海里不断生长的岛屿,最终会变成大陆如何开始真的要开始吗?给我一个理由1.速度,一眨眼就穿越了2.包含反馈,能够定位问题的所在3.自动化4.设备无关(数据库,网络,文件系统)如何开始步骤1.确定修改点2.确定测试点3.解依赖4.编写测试5.修改和重构如何开始工具1.CppUnitLite2.由CppUnit的作者所编写,一改复杂的使用方式3.TEST宏,CHECK_EQUAL宏,CHECK宏4.TEST_F宏(fixture)如何开始codeTEST(测试名){测试代码CHECK_EQUAL(预计的结果,代码计算的结果);CHECK(条件);}如何开始经验1.将被测试的软件编译成lib/dll,这样可以新建一个独立的solution来布置测试代码,并且不会对原来的软件造成影响。如:TTYGSZ_Lib2.类的成员变量也许protected会好一点,因为在测试中派生类需要访问它们,来验证结果如何开始经验3.可以放弃测试MayXXX的方法。因为测试他们需要准备很多伪对象,而他们实际做的工作仅仅是ifreturn而已更多的考虑有种单元测试相关的软件开发技术,叫做测试驱动开发,可以考虑作为下个项目的开发方案之一单元测试很好很强大,但不是银弹Codereview对交流和成长更有帮助阅读《修改代码的艺术》
本文标题:单元测试讲义
链接地址:https://www.777doc.com/doc-3574314 .html