如何测试代码重构

2018-03-09  本文已影响153人  编走编想

一、前言

我最近做的主要工作是重构我们系统的核心功能。做过代码重构的同学都知道,代码重构很多时候是个费力不讨好的事情。因为代码重构是在不修改软件功能的情况下,对软件内部进行调整优化。

不修改功能便意味着从业务角度讲,这项工作不会带来什么收益。因为这一点,代码重构工作通常难以得到充分的资源投入。而且,代码重构工作不同于普通的代码开发,代码重构往往需要投入核心的高水平的研发人员,所以会占用更多的研发资源。

另一方面,代码重构不仅不会给业务带来收益,一不小心往往还会带来很大的风险,尤其是对关键的代码、核心的代码重构。因此,大领导出于业务和研发资源等方面的考虑,通常对代码重构都持有非常谨慎的保留态度。

但从研发工作角度讲,代码重构往往是必要的。具体到我所在的项目,最近做过调查,团队中已有近90%的研发同学表示自己项目中的代码有明显的难以理解、难以修改的问题。更有同学表示因为经常接触烂代码,自己以忍无可忍,每天的工作就是打补丁,毫无成就感可言。

另外,通过代码检查工具,发现代码在圈复杂度、重复率方面有严重的问题,具体的数据就不展示。所以,从直观感受和量化指标上,都说明我们的代码急需重构。

所以,从研发工作角度看,代码重构的必要性往往是存在的。而从业务层面看,领导往往是不喜欢(至少是不主动支持)代码重构的。

那如何协调这个矛盾呢?

其实代码重构的实施主要存在两大问题:一是研发资源的问题;二是重构质量的问题。第一个问题不在本文的范围内,谈谈第二个问题。质量问题说白了就是代码重构之后功能还是否正确。如果代码重构只能功能不正常了,那代码再漂亮也没用。如果能保证代码重构之后不出错,那领导自然就会少很多顾虑,代码重构工作也更容易实行。

接下来就谈谈如何更好地测试重构之后的代码。

二、测试方案

任何软件开发都离不开测试,代码重构更是如此,而且代码重构往往会带来更多的回归测试工作量。假如有充分的测试用例和完善的自动化测试保证,那大量的回归测试往往不是难题。但开发、产品、测试换了一茬又一茬,早期的需求已被埋入尘土;早期工作方式简单粗犷,代码都没写好,有何谈自动化测试。所以,充分的测试用例和完善的自动化测试很多时候是不存在的。

那怎么办?在时间紧,任务重的情况下,怎么能在短时间内将这些测试工作准备好?

方法一:对比测试

测试用例,简单说,就是给定一个场景(输入),验证在这个场景下软件的行为(输出)。所以定义测试用例就需要定义测试时的输入输出和验证规则。

但在代码重构中,因为软件的功能并未增加,因此也就没有增加新的测试用例。并且,重构前的老系统本身就提供了大量的测试用例。为什么这么说,因为重构之后的新系统的各项业务行为只要和老系统保持一致,那就可以说是正确的。

所以,对于代码重构工作,测试用例的编写就被大大简化:只需定义输入,无需定义输出,将老系统的输出作为输出即可。同时,验证规则也简化了很多,各项数据通常只需和老系统保持一致,少数的不能完全一致的数据,只需验证其满足一定规则即可。

具体方法:

定义测试用例输入,分别调用新(重构后的系统)、老系统。用老系统的结果校验新系统,从而降低测试的工作量,提高测试效率。

方法二:导流测试

方法一可以帮助简化对测试结果的验证,但是测试输入还是要想办法丰富起来,否则漏掉一个场景就有可能放过一个 bug。

对于老功能,需求早已丢失,当年设计开发它的人也已不在,那如何为这样的确实需求的功能设计测试用例。有一个方法是直接使用线上的请求测试。

具体方法:

通过使用 Nginx 的 ngx_http_mirror_module 模块(或其它技术,如 tcpcopy),复制一份线上的请求,然后将这份复制的真实请求导向部署了重构版本应用的服务器。然后再通过方法一介绍的对比测试方式,比较线上应用和重构后应用的输出结果(返回值、数据库记录等等),从而验证代码重构的正确与否。

但是这种测试方法有一定的局限性。简单来说,这种方式适合测试读接口,不太适合或者说是难以测试写接口。因为测试请求来自线上,如果被测服务器同样部署在线上环境,那写接口就会对用户造成应用。如果被测服务器部署在测试环境,需要在测试环境完整同步一份线上数据,这需要相当的基础测试设施的支持。

三、总结

上面介绍了在面对代码重构时的一些测试方法,希望能帮助大家安全顺利的上线代码重构,让项目的代码质量越来越好。

上面介绍的方法解决的问题范围是有限的,我工作接触到的问题也有限。所以欢迎大家能针对这个问题提出自己的意见和方案。

我的技术公众号“编走编写”
上一篇下一篇

猜你喜欢

热点阅读