测试 | 让每一粒尘埃有的放矢
对很多开发人员来讲,测试人员是扫雪工,没什么真本事。并且,在他们自己构建代码时,也对测试不屑一顾。要么是抱着老子天资聪慧,用不着这些繁文缛节的官僚流程;要么是觉得写测试并没有什么“实际”的贡献,花了大量的功夫,似乎什么都没有推进,什么实质性的feature都没被实现,只不过是一堆检验性质的监视器罢了。
Linus对测试的看法就完全不一样。在《关于git的主要维护者滨野纯的访谈》一文中,有这样一段论述:
Linus对每个贡献者都很看重。我那时候也是,Linus对我说,虽然你的提交没有被采用,但测试用例还是能用的,针对现在的实现,你稍微修正一下吧。
可见,在Linus的眼中,testcase是被认为是大于或等同于功能性开发的重要东西。因为,即便是你开发的功能性代码没有被使用,而接受你的测试集本身,也可以用来作为鼓励你的重要东西。
在我看来,很多人对测试的理解不太透彻,也缺乏深度。其原因不是这个人的技术有问题,而是这个人所体现出来的个人习惯,或者工程素养有问题。
让我们举一个最简单的例子,如果你发现你的电脑反应迟钝,想要重装系统,你会怎么做?
如果电脑里的文件比较少,估计很可能就直接重装。而如果文件稍微大一点,或许会拷贝几个重要目录。而如果文件太过复杂,大部分人会在经历了半小时的仔细核对后,毅然放弃,直接撸起袖子就开始重装,并会在心里骂上几句:神马破玩意儿,浪费我这么多时间!管那么多干嘛,旧的不去新的不来!
而什么是良好的工程素养呢?就是首先,在发生重装系统这个事情之间,他就会好好规划自己的文件安放问题,并作出一些预案。再来,如果真的是拿到一堆烂摊子,他也不会这么鲁莽。拥有良好工程素养的人,一定会按部就班地将所有文件仔细核对后,做出相应的备份,再记录好相关的引用关系。甚至还会优先考虑失败预案,最后才是做重装系统这一步。
重装系统就像是爆破一栋楼房。拙劣的工程师,只会不管三七二十一,直接行使最畅快的“爆破”动作。而好一点的工程师,会留出足够的预案和备选,至少要做到先把爆破附近的无关人员疏散走吧。而卓越的工程师,则会精密地去制定自己的方案,力求做到让每一粒尘埃都有的放矢,让每一块砖石在掉落地面的时候,都能够被救生毯准确接住。
那这与开发、测试有什么关系呢?其实,开发就是爆破的炸弹,直接行使最抢眼球但却是最简单粗暴的部分。而测试是默默无闻的,是预案、是隐线、是为每一块飞落出去的砖石垫底的毯子!
表面上,这堆毯子并没有什么用,因为你的任务是爆破,不是生产毯子。可是,一场不顾影响、不顾周围人员死活的爆破,到底是破坏性的战争行为还是建设性的工程行为?这就完全取决于你是否为这场爆破做了规划、做好了预案。
测试,是开发的防弹衣、兜底布,让你的开发爆破行为不再血水四溅、尸横遍野。它是你自己的保护伞、是周围人员的防护罩,让你的开发行为从暴力性质变为建设性质。
而另一方面,编写测试集,并没有想象中的那么缺乏技术性。某种意义上来讲,测试集(特别是Regression测试集)的编写,其实就是“技术壁垒”的真正所指。Regression测试的建立过程,其实就是一个团队成长过程的积累。每当遇到一个大坑,它的fix和修复后的testcase,就会被吸收进Regression测试集,永远地服务于未来的开发。
试想,如果你的这些fix,都无法以Regression测试集的方式被吸收,那请问这些曾经淌过的浑水和经历过的伤痛岂不都白费了?它无法被不断复用,也无法被用来服务未来的开发,其价值,岂不是就这样损失了?
这些通过实践和历史累积下来的东西,才是真正的“技术壁垒”!它不可能是哪个天资聪颖的开发人员的灵机一动或者突发奇想就能做出来的。它是确确实实的、在每一个历史节点上的、在每一段呕心沥血的战斗后,保存下来永远服务于未来的历史资产!这种靠岁月累积下来的东西,牢固而强大,不是一朝一夕、或者某份天资聪颖就能取代的。这才是一个组织的技术沉淀,是真正不可撼动的宝贵资产。
而这份资产是什么呢?就是最开始谈到的,被大部分开发人员所忽视的测试。