王辉的博客

是什么让我对未知世界始终充满热情?

0%

软件测试从本质上讲,和其它领域的测试一样,都是为了验证该能用的功能都能用。拿造自行车来讲,出厂之前得试一下吧,保证脚蹬刹车等都好用。软件也一样,发布之前通过测试来完成产品验收。可不一样的是,自行车出厂之后,是什么就是什么了,很少有人会回来要求给自行车添加新的功能。可对于软件来说,这却是家常便饭。不变和变之间,虽然只有一字之差,却意味着思维方式上本质上的区别。

对于自行车的测试来说,它们也是一成不变的,就是为了在车子出厂之前,利用他们给车子打下个合格证。而软件呢,是变化的,不断成长的,主要体现在新功能的引入。可限于软件这种产品的复杂性,新功能的引入是有风险的,它们可能破坏既有的功能。所以在面对这些风险的时候,软件中的原有测试所扮演的角色,就是保护这些既有的功能在新事物的入侵下安然无恙。

所以说要用发展的眼光来看待软件测试,同一个测试,随着时间的推移,虽然说在本质上讲是不变的,但它们在不同的生命阶段扮演的角色的侧重点是不一样的。

如果一个接口后面,只有一个实现它的类,那么这个接口,还真正有必要吗?

我觉得百分之九十的人提出这个问题时的情形是应该这样的:他没有用接口的习惯,在能少则少的指导思想下,只要是只有一个类,他绝对不用接口。突然有一天,他看到他的一个同事,在写具体的类之前,先把接口写好了并且写了相应的文档解释这个接口应该提供的服务,可之后只实现了一个类。他就问了,这个接口有必要吗?这个问题暂且先放下不说,看完另外一种情形,在加讨论。

试想我们有一段写好的代码,用了接口,接口后面,有两个具体实现此接口的类,突然有一天,我们发现,其中有一个类,以后不会再被用了,于是乎就把这个类给删了,这时只剩下了一个类,那么敢问,是不是把接口也给删了呢?

以上两个问题,其实都是在对同一件事发问,但是出发点不一样,但我觉得这两个问题结合在一起回答,会使答案更加清晰。

先分析第一种情况,有意思的是,他那个同事为什么在实现类之前,先把接口给定义了? 先实话告诉你,我就是那个喜欢用接口的人。所以我就都交代了先。我之所以先写了个接口,倒不是因为,一下就想到了,接口后面会有多少具体实现的类,而是为了想先搞定依赖于此服务的另一模块。打个比方吧,我正在写的这个模块需要一个缓存服务,但缓存不是它的核心业务,所以说它根本不关心缓存具体是怎么实现的。所以我就写了个抽象的接口先,并清楚的描述此接口应该提供的服务,至于如何实现,一字没提。更加给力的是,在写那个具体的缓存类之前,依赖于它的这个模块的单元测试我也写好了。欢乐吧!最后,这个缓存怎么搞,我可以选择自己搞,也可以给外包出去,反正,协议都已经写好了。

好了,先小结一下,在这里接口的用处很明显,它定义了一个服务是什么,而不是说,服务是如何实现的。如此看来,写接口有利于专注在核心业务上,有利于软件的模块化,有利于增加代码的文档解释率,有利于提高模块的可测试性,并且还可以通过分布式工作加快开发进程。当然,一切的前提,是我们可以抽象出来我们所需要的服务。否则,都是扯淡。

现在再看第二种情形,我们需要把接口给删了吗?恐怕,想删都没那么容易了,为什么?因为,这个接口在测试里被用了,这个接口上有完善的文档。当然,估计也没多少人会提出要不要删它的这个问题。

得嘞,在看看开头的问题,是不是显得很幼稚?

项目里是给覆盖率定义了警戒线的,可我们却一直在覆盖率下面。

测试覆盖率为什么上不去?因为我们没有在那上面下功夫。为什么没有下功夫呢?因为我们没有预算。我们会有预算吗?不会,因为做测试应该是每天工作的一部分,是需要一直在后台执行的。

对与新写的代码,我很认同这一点,没有测试的代码,不能称之为代码。可是对于已经写过的老代码呢。我觉得我们需要预算,预算的目的是为了还过去欠下的技术负债。