为什么写这篇文章
现在的工作需求,让我有必要总结和整理一下。
凡事都有适用的场景。首先这里我需要提示一下,这里的信息,可能并不普适。
但是可以肯定一点的是,有些人,不论做事还是写书,上下文还没有交待清楚,就对你说单元测试如何重要,这种是极为无耻的。
是的,我是说无耻。因为说风凉话的人,他们不需要像那些奋战在一线的程序员那样,需要面对结果质量与进度和成本,以及维护性之间的考量,他们只需要在意自己说的话是不是看来永远正确即可。
这么说吧,一个想要他说的话永远正确,只需要故意将上下文删除即可,这也就是人们常说的站着说话不腰疼,或者永恒正确的废话,或者何不食肉糜之类的正确但无用的话。这些话往往常出现在书籍上。
但是,现实中,我们每天都需要面临痛苦的选择:是让自己良心好受一些,写出质量过得去的程序,还是让老板看到,我又出活了这样的表面文章。
所以,我们必须要考虑如何测试,以及如何避免重复相同的错误这样的问题。
然而,测试从来不是一件简单的事,事实上,我的硕士论文写的就是如何在被测对象升级之后,自动测试的脚本,能够95%以上自动升级的故事。这个我们不多说了。但大家都知道这是一个困难的事情。所以我的论文开篇讲的是自动测试的消亡史。
讲到测试,我们就不得不考虑测试的方法。
所有的书上,都强调Unit test是必不可少,多么重要。
这点了解我的人都知道,我是嗤之以鼻的。
正确的事,就好比亚当.斯密的《国富论》,认为自由竞争是是经济的基石;而事实是,人们总会有想尽办法使自由竞争失效。
同样,这些看似正确的废话,只能带来灾难。软件行业的灾难性失败还少吗?这些大公司没有做单元测试吗?
以微软为例,2003年,当时我还在某为,听说微软过了CMM2级,我说了一句:微软从此再也不能开发出有完整度的软件。一语成谶。
铺垫这么多,就是想对一些人说:凡事需要考虑上下文,不要被所有的书里都认可的话所蒙蔽:所有的写书的人,大多没有在一线工作过。
单元测试VS模拟(或仿真)程序
后面我们来比较一下这二者
单元测试的适用范围
1。 相对简单的程序或产品。
2。 与设备无关的程序或产品。
3。 需求变动相对慢的程序或产品。
4。 设计良好,接口清晰,与人机界面交互不多的多线程的每个模块或层之间。
上述为一般的单元测试能取得良好效果的上下文。
单元测试的问题
对代码有依赖。
这显然是最严重的问题。
有人说,为什么我要极客编程的原因正是如此,因为以前测试与研发是相对的,因为体制要求如此,但测试发现,研发的人可以随意改代码,所以白盒测试就消亡了。
所以,管理者就想到让程序员吃自己的狗食这样的损招:自己写自己的单元测试------反正嘴一动就可以了,这多简单。他们不考虑这么做带来的后果是什么。
这是一个悲哀的时代的原因是真正的程序员,已失去是了话语权。
那么有人说,是你自己的狗食,做得不好吃是你自己的问题。
然而事实真的是这样吗?
需求变动,产品经理认了客户当干爹,他敢对干爹说不吗?
还是苦一苦程序员吧。
设计错误,所有的PMP(我不是说PMP认证,我是说拍马屁那个PMP)的组长,敢对总工说不吗?
还是苦一苦程序员吧。
接口常变动,程序员同样没有权力找横跨多个部门的技术官僚体系去说理。
还是苦一苦程序员吧。
所以,这狗食难吃,也许只有不到1%的问题,在程序员。
所以,程序员现在不仅要捏着鼻子做难吃的狗食,还要自己吃了。
当然我们需要肯定单元测试的价值
如果你有良好设计的复杂的程序,所有的模块相对独立,接口相对稳定,
并且这个程序是多线程程序,那么单元测试是能发挥出极大的价值的。
如果再加上我写的论文里描述的,当被测对象发生改变时,自动测试脚本也能自动升级,显然对程序员是有利的。
当然,这是永恒正确的废话。
因为分工是你程序员浇水,官僚体系吃桃子。
呕,我忘了说,这种分工很公平:一棵树,一人一半,你要下面,我要上面。你一直浇水,我一直吃桃子,对了,老吃桃子也很累人的,你们浇水人不会懂我们的痛苦的。一人一半,很公平,放称上称称,一定一样重的。。。
或者说,除非这项目是你一个人在写。
多数情况,单元测试害处多于利益。
原因很简单,导致这种情况的官僚体系,是无人问责的(单向向上体系)。责权不对等。当然,他们吃桃子也很累,我也很有同理心的。
所以总结:
一个人的项目,而且项目很复杂,设计可控,接口清晰,需求清楚,而且你要对被测的对象非常了解,才可以。
模拟(或仿真)程序
当然一般我们是指模拟程序。除非有条件(作设备仿真)。
人们有个误解,认为互联网程序代表程序员,这显然是错到离谱,离了大谱。
广大的程序员,是需要与设备或硬件打交道的。
所以,模拟或仿真程序,是至关重要的。
原因是绝大多数公司,无法提供足够的硬件给程序员。
程序员的困难在于,有困难无处去说,比如说,我需要行拿到设备,才能逐渐的了解它的习性;
但领导却坚持认为,你是懂的,你非常懂。
等你刚懂,这个项目完事了,新的设备又到了。
所以,程序开发是个动态过程,这些话,领导是无法理解的,因为中国的情况,目前的领导都是硬件出身,麻麻不懂。而且也不讲道理。我这么说是有依据的。
在这样的情况下,写单元测试,是相当离谱的。
但是,写模拟程序却是非常必要的。
这是从技术开发和技术管理两个视角来看的。
因为模拟程序的仿照对象仅仅是我们的target,而unit的服务对象却是我们的程序。
这个你稍微理解一下就懂了。一个是对哈雷彗星,另一个是对哈雷将军。
也就是说,我们自己写程序,是最不可信的,因为你在信息的最后一道工序,没人在乎你。
但设备不同。
所以,不论你如何改代码,都不会影响simulator。
这是最关键的要点。与unit test不同。
我常说,第一点占75%以上。
但是后面的不重要的理由我们也要说说。
资产保值性
资产保值这件事,也是有水分的。因为你得是"资产",才有必要保值。
一堆垃圾代码,它就不是资产。
单元测试的代码,往往如此。因为它要测的对象如果是个垃圾,它就一定是垃圾。
可是,simulator却不是这样的。
因为它mirror的对象是真实的设备。
随着公司工程的一年一年的积累,这个simulator会变成emulator的一部分,最后会变成产品的一部分,最后,会比产品更好。
以ABB的机器人为例,了解过的人都知道它的simulator有多强。FPGA的程序,DSP的程序,直能能跑。机器人也是三维CAD动画模拟出来的。
用户不需要买robot就能完全与买了一样给机器人编程。
这个算是15%?
管理角度
利用分工,也就是说,大公司,可以专门派专人写simulator,这点其实非常有价值的。注意是专岗。
如果有公司这么做,说明这老板有水平。
尽管中国大多是垃圾公司,管理极为垃圾。
但如果你的老板有这水平,恭喜你。尽量多干几年。
啊对了,你不可能设立专岗写unit test。前面这我解释得好多了。
后记
可千万不要以为,单元测试不重要。
其实我也写的。
因为我能做到可控。
因为是我一个人在干。我对我的能力也相当自信。所以我用。
但我尽最大可能,会集中精力写模拟程序,因为太必要了。