KOK球盘体育
当前位置: KOK球盘体育 > 单元作文 >

各位都是怎么进行单元测试的?

时间:2020-03-10 06:38来源:未知 作者:admin 点击:
KOK球盘体育

当前网址:http://www.wassei.com/danyuanzuowen/2020/0310/725.html

  工作中写C++,不敢自称大神,也来斗胆分享(安利)一下经常使用的单元测试框架。

  在Google工作,尤其是写C++的程序员,常常离不开写单元测试。所幸的是,Google提供了很成熟,也很使用的单元测试框架gtest和gmock。gmock是gtest的一部分,也可以说是gtest中比较advanced的topic。至于使用场景(避免在单元测试代码中向production服务发送rpc啦,读取production的资源啦,绕过一些production环境中必须的权限来测试代码的逻辑啦)会在后面举例说明。

  正式开始写长一点的C++程序之后,就会逐渐萌发出写unit test来保证代码正确性的需求。例如,一开始写的单元测试可能是这样的。有个函数实现加法:int Add(int x, int y);我们最开始会使用assert来做一些基本的测试:assert(2 == Add(1, 1)); // 正常的用例assert(1 != Add(1, 1)); // 异常的用例assert(sum Add(num1, num2)); // 溢出异常?如果num1和num2都是正整数的前提下,sum应该blablabla其实在我们一开始学习写单元测试的时候,老师或者有人生经验的资深码农就已经告诉了我们写单元测试的一些原则:1)测试用例能验证函数的正确性(这条都通不过就……);2)测试用例尽可能涵盖边界条件(例如遍历一个链表,头指针是空,只有一个节点,链表有N个节点,N是问题描述下允许的最大节点数等等);3)一些异常和错误处理(例如往一个函数里传入空指针,传入空串,这个函数能否打印一些log,返回错误码,实现加法的Add函数如何检测和处理溢出等等)最理想的情况下(时间很多!),应该尽量多写测试用例,以保证代码功能的正确性符合预期,具有良好的容错性。如果代码较复杂,条件分支较多,测试用例最好能覆盖所有的分支路径。上述原则一般解决了很多“应该测试什么”的问题。

  工作了一些年头,我觉得单元测试起到的最重要作用其实是:让人在修改代码之后能感到安心,踏实(单元测试跑过之后能比用飘柔更自信)。只要跑一把单元测试,就能自动化验证程序逻辑的正确性,而无需在提交代码之前提心吊胆、担心会漏掉什么情况没有处理或者自己新加入的逻辑制造了bug。

  其实,写单元测试是很繁琐的。因为要考虑的琐碎的东西其实很多,有时候为了方便,可能还要修改原来已经写好的接口(没错,我菜,我没有先写测试再写实现,我不fashion,我没贯彻test driven development原则,我活该_(:з」∠)_)。

  所以,为了能在写单测的时候可以偷点懒,也为了代码读起来舒服一点,gtest框架提供了很多宏:

  高清无码,4K全彩错误提示,你不仅知道哪个test case挂了,你还能知道当前输出是啥,就不用再慢慢打log看了。

  框架帮我们做了一些琐碎的事情,我们就能提高工作效率,实现work life balance(提早下班,删掉)。

  而且在使用上,使用gtest也很方便快捷,只需要(不准确,只是大概这样):#include gtest/gtest.h // 当然偷懒也要include头文件,按照基本【哔~】

  ————————————GMock——————————————简单说说GMock有些代码,总会有些复杂的依赖。例如使用了某框架的API来发送RPC请求,读取云上的资源BigTable或者需要连接到某个服务请求一些权限获得一个token等等。这些逻辑会产生一些IO和网络上的开销,在production中使用无可厚非,但如果每个人写代码跑单元测试都要调用这些逻辑,从而又产生很多没什么实际意义的开销(例如发送一些dummy的RPC请求),这对生产环境的资源会造成一定量的浪费。

  例如有个类,叫TableManager,他的功能包括在云端创建一张数据表,获得一些表的属性,支持对表进行查找。一些代码作为client使用了这个类,在云端创建表和存取一些数据。但单元测试代码并不希望真的去读写那些在生产环境里的资源,这时候就需要为TableManager类创建一个对应的Mock类来“绕过”生产环境了。class TableManager {public:// 创建一个名为“table_name的表,成功就返回true。如果table_name不合法,该表已经存在(这个方法已经被调用过了)或者TableManager本身没有在这个方法调用之前获得合法的token,创建表的请求被拒绝,这个方法就会返回false。virtual bool CreateTable(const string& table_name);

  Mock了TableManager类之后,我们既能测试代码的功能,又能避免浪费生产环境的资源,是不是有点小愉快?

  Google内部有很多功能丰富的开发工具和库,而且文档齐全,经得起岁月的考验,很多优秀的工具和框架都已经开源(例如GTest框架,Protocol Buffers,GRPC等等),实在是居家旅行,杀人越货,开矿推塔,仁义无双,优势很大,吃肉人族,上天入地的必备佳品。

  作为一只菜鸡,东西写得不是很好,就做一点微小的工作,分享给大家,谢谢各位 :D

------分隔线----------------------------