毕业找工作那会,有个开发的同学被分配去做测试,当时很不理解。为什么他平时都是用 Java,怎么去做测试呢?当时对测试的认知就是点点点。
在工作一段时间后,对于测试依然有一定程度的偏见。为什么有偏见,还不是因为无知!人类对于不了解的东西,很容易形成偏见。
当时觉得开发的功能,进行一下简单的测试就可以了,功能正常就 OK 了。也一直是这么做的,也没有出什么大问题。毕竟框架都是现成的,写写业务代码没啥难度。
后来自己开始开发新的通用模块,上层很多业务都需要用到的功能模块。第一版功能实现后,后续就不怎么敢修改了。即使修改,也是战战兢兢的,担心引发大规模的问题。如果只是自己用,出问题了还可以控制,关键是我们开发的是 API,只要出问题,依赖我们的各个程序都会有问题,这个影响就不可控了。并且问题总是会延迟很久才会出现,出现后定位修复提交得时间,重新出版本也需要时间,对方替换验证也需要时间,整个周期太长,影响面很广。
所以,每次提交底层代码前,都会进行“充分”的测试。当然,这个充分是自己以为的以及环境允许的充分,因为很多环境都不在了,不能保证改动的每个地方都能被测试到。所以,每次提交底层代码,依然会紧张,因为我不能 100% 的确定代码质量。
只要提交代码,就有犯错的可能。如果对于错误的处理没有一系列完善的措施,就会导致人人都“不求有功,但求无过”的心理。虽然代码写的很恶心,但是基本功能都是被验证的,所以不会想着去优化;虽然代码中有雷,容易导致别人改代码加功能时踩坑,你也不敢去改,毕竟没有完善的环境给你测试。所以,代码从提交后,就基本不会变了,虽然各种不友好。
踩了坑,你对问题的认知才会更深刻。才会更加知道测试的重要性。如果只是停留在知道上,那么依然是止步不前。重要的是,测试到底多重要,怎么保证测试的质量,怎么用测试充分保证代码质量。
为了对测试有更深刻的认识,前后陆陆续续看了测试相关的书,譬如《谷歌测试之道》,《微软测试之道》,《持续交付》,《测试驱动开发》,《自动化测试》等等。研究及使用了 Google Test, CppUnit等 C++ 测试框架,对于 Python,Golang 的测试也有了初步的了解。对单元测试,冒烟测试,集成测试,灰盒测试,白盒测试,黑盒测试都有了一定程度的认知。了解的越多,对测试的重要性也越认可。
测试可以分为自动化测试及人工测试。自动化测试依赖写好的大量的测试代码而保证质量,而人工测试通过手动操作来保证质量。手动测试依赖UI测试用例,很多情况下属于黑盒测试,很多功能并不一定能够覆盖到。但是人工测试不可少,因为有些功能必须有人的介入才能够确定是否正确。自动化测试和人工测试结合起来,能更好的保证质量。
当然,自动化测试和手工测试都需要充分的测试用例。这需要对功能,对代码,对业务的深刻理解。如果对业务没什么理解,就各种设计测试用例,测试用例的质量就会大打折扣。如果只是为了走个形式,为了写测试用例而累测试用例,也没这个必要,个人没成长,对业务也没啥帮助。
自动化测试用例需要反馈,譬如代码覆盖率,执行结果的自动反馈等等。和持续集成或者持续交付结合起来,才能发挥其最大威力。
有一种很好的保证代码质量的方法:测试驱动开发(TDD),其理念真的是非常好,实际作用也很大。当把它引入代码开发时,对于功能的完整性,对于代码的可读性,代码的质量等都有很好的保证。有了前期开发的测试用例,后续改动引起的问题,测试用例一跑就能发现,代码质量得到了很好的保证。
之前有利用 Jenkins 搭建了持续集成的平台,从代码提交,到测试,都是自动化的流程。测试用例跑不过时,覆盖率不达标时,Coverity 新增问题时,都会通知相应的代码提交人。那时真正的意识到持续集成的好处。
在学习及实践了自动化测试,搭建持续集成平台后,依然有个问题绕不过:你怎么保证你的测试环境是充分的,是完善的?因为测试用例要基于具体的环境才能明确其效果。如果环境不稳定,你怎么保证测试用例的执行情况?
这个问题困扰了我很长时间。为了测试充分,你得有充分的测试环境。如果你的环境依赖于第三方,譬如设备,你怎么保证?你不可能搭建各种设备环境,单独给你测试用,这样成本太高了。为了解决这种问题,你可以通过 Mock 实现,可以开发模拟器,模拟和设备的交互,保证测试环境的稳定。
18 年底,我开发了协议模拟器,对代码改动后,先用协议模拟器进行验证。不用费时费力的去借设备,开发效率得到了很大的提高。有了模拟器,我敢对代码进行修改和完善,因为我有环境,可以通过具体而详细的测试用例保证质量,真正的藏到了环境完备和自动化测试的甜头。
测试往往是一个整体的过程,需要整体的设计与规划,不应该想到什么就做什么。当测试用例及测试环境完善后,通过测试用例倒逼代码的完善和重构。在没有充分的测试用例的情况下,谈代码的重构都是扯淡。这种做法的后果就是埋下无数的雷,后人排雷不知道要用掉多少人力和物力。排雷多了后,人的斗志和信心都被打磨的干干净净,也不会有完善优化代码的想法。
如果有一个完善的持续集成(持续交付)流程:代码提交后触发编译,代码扫描,单元测试,进而冒烟测试,再是集成测试,最后部署到生产环境中。整个过程形成一个闭环,及时反馈,使得引入的错误及缺陷及时被发现,减小代价。
现在也逐渐明白了大厂的开发测试工程师那么吃香的原因了,保证代码质量真的很重要。任正非任老爷子说:我们要从最基础的编码质量做起,视高质量代码为尊严和个人声誉。真的很认同这个观点,保证自己代码的质量本是是基本的事,但很多时候我们却保证不了。所以他才把代码质量提到那么高的高度,而代码质量离不开测试。代码质量保证了,功能才能稳定,稳定可靠的功能就是最好的宣传。保证代码质量就是程序员练内功,内功扎实,才能在上面构建更多的可能性。
推荐阅读
任老爷子的《全面提升软件工程能力与实践,打造可信的高质量产品》。
有疑问加站长微信联系(非本文作者)