测试驱动开发系列之六--给遗留代码做重构
2014-05-04 12:04
295 查看
13.1 遗留代码改动准则
用测试驱动遗留代码的改动,在改动前为遗留代码增加测试,测试驱动新代码的开发
13.2 童子军原则
在离开宿营地时要让它比你来时还干净。这并不意味着所有的垃圾都要马上清理干净,但你不能让它变得更糟。
13.3 遗留代码改动步骤
发现改动点
你要先找到现存代码中你认为需要改动的地方。
找到测试点
在发现改动点以后,开始考虑如何测试它。在哪一点能更自然地感知代码中发生了什么,代码又是从哪里得到输入的,测试点通常很明显地存在于由函数调用形成的接缝中。
测试点不一定非要是接缝,全局变量尽管我们很不喜欢他们,但它们可以提供测试点。传给函数的数据结构也可以提供测试点。
断开依赖
为了把遗留代码放入测试框架中,或者得到对某些测试点的访问,我们不得不断开依赖。在TDD的过程中我们使用了链接器,函数指针或者预编译的测试替身来断开依赖。有时候断开依赖的风险太高。我们会看到几个不同的断开依赖的方法:感知变量使已有的调试输出作为感知点以及插入监视点等。
为了断开与全局数据的依赖,你可以把对问题全局数据的访问封装到一个访问函数中。然后在测试的过程中你可以重载此访问函数来获得对全局的更好控制。
测试点
有了测试点,就可以写一些测试来识别及保护遗留代码的行为了。
做修改并重构
当一些保护测试就绪后,就应该可以比较安全地应用一些重构的变化了。
13.4测试点
我们需要测试点来确认对代码所做事情的理解。有些测试点很容易找到,有些则比较困难。
接缝
接缝就是这样一个位置,在那里你可以改变程序的行为,却不用修改那个位置。这些接缝就是最好的测试点。
全局变量
全局变量可以用来作为测试点,同时也是一种把测试所需的值传入被测试代码的机制。一旦代码已经在测试保护之下,你就可以把全局变量封装起来了。
感知变量
感知变量在从长函数中获得对难于到达的或者中间的结果时很有帮助。一个感知变量可以用来检查一系列计算中的中间值,状态变量其中的一个值,或者也可以是一个循环执行的次数。感知变量的引入不是一种永久的方式,而是在解开长函数时的一个临时步骤。
调试输出感知点
从长远角度来讲,我希望减少对调试输出的依赖。但是我们是在遗留代码上工作,不太可能把所有问题都在一天之内解决。
嵌入监控
我们可以在代码中插入一个特别的函数调用,来把某些信息报告给测试用例。嵌入监控可以在测试正在运行时多次读取某一个特定的感知点。把遗留代码放入到测试框架中可能本身就是一件很有挑战的事情。
13.5两步结构体初始化
如果我们想要在测试数据上做点小变化,可以把两步初始化分开,初始化放在setup()函数中,把每个测试用例微小的数据变化放在各个测试用例中。在应用这个想法的过程中,你可能要创建一些辅助函数,并且你会发现他们实际上应该属于产品代码。
13.6崩溃直到通过
让它能编译 让它能链接 找到运行时依赖 修正运行时依赖 增加更多的C语言遗留代码测试
13.7鉴别测试
可以用测试来捕获当前有价值的行为。如果你对代码理解得好到足以为它写出测试来,你可能对它的理解就足够好到可修改它。
仿制对象能够帮助我们更好的鉴别测试。
13.9测试驱动缺陷修正
当定位缺陷以后,写一个测试来揭示这个缺陷。要抵制住马上去修改缺陷的诱惑。生命是有限的,你不希望在干掉一个正在处理的缺陷时又引入一个新的缺陷。并且我们知道缺陷往往都挤在一起。
13.10增加策略测试
一个有着遗留代码的产品团队应该考虑主动地增加测试来找到已有的缺陷及保护重要的功能。你能花在为遗留代码写新测试上的努力是有限的,因此要有策略。
在遗留代码下工作需要的是一种思想,一种基于我不会引入问题,我会让事情变好的思想。我们会开始偿还技术负债的本金并且减少将来用这些代码时将付的利息。
用测试驱动遗留代码的改动,在改动前为遗留代码增加测试,测试驱动新代码的开发
13.2 童子军原则
在离开宿营地时要让它比你来时还干净。这并不意味着所有的垃圾都要马上清理干净,但你不能让它变得更糟。
13.3 遗留代码改动步骤
发现改动点
你要先找到现存代码中你认为需要改动的地方。
找到测试点
在发现改动点以后,开始考虑如何测试它。在哪一点能更自然地感知代码中发生了什么,代码又是从哪里得到输入的,测试点通常很明显地存在于由函数调用形成的接缝中。
测试点不一定非要是接缝,全局变量尽管我们很不喜欢他们,但它们可以提供测试点。传给函数的数据结构也可以提供测试点。
断开依赖
为了把遗留代码放入测试框架中,或者得到对某些测试点的访问,我们不得不断开依赖。在TDD的过程中我们使用了链接器,函数指针或者预编译的测试替身来断开依赖。有时候断开依赖的风险太高。我们会看到几个不同的断开依赖的方法:感知变量使已有的调试输出作为感知点以及插入监视点等。
为了断开与全局数据的依赖,你可以把对问题全局数据的访问封装到一个访问函数中。然后在测试的过程中你可以重载此访问函数来获得对全局的更好控制。
测试点
有了测试点,就可以写一些测试来识别及保护遗留代码的行为了。
做修改并重构
当一些保护测试就绪后,就应该可以比较安全地应用一些重构的变化了。
13.4测试点
我们需要测试点来确认对代码所做事情的理解。有些测试点很容易找到,有些则比较困难。
接缝
接缝就是这样一个位置,在那里你可以改变程序的行为,却不用修改那个位置。这些接缝就是最好的测试点。
全局变量
全局变量可以用来作为测试点,同时也是一种把测试所需的值传入被测试代码的机制。一旦代码已经在测试保护之下,你就可以把全局变量封装起来了。
感知变量
感知变量在从长函数中获得对难于到达的或者中间的结果时很有帮助。一个感知变量可以用来检查一系列计算中的中间值,状态变量其中的一个值,或者也可以是一个循环执行的次数。感知变量的引入不是一种永久的方式,而是在解开长函数时的一个临时步骤。
调试输出感知点
从长远角度来讲,我希望减少对调试输出的依赖。但是我们是在遗留代码上工作,不太可能把所有问题都在一天之内解决。
嵌入监控
我们可以在代码中插入一个特别的函数调用,来把某些信息报告给测试用例。嵌入监控可以在测试正在运行时多次读取某一个特定的感知点。把遗留代码放入到测试框架中可能本身就是一件很有挑战的事情。
13.5两步结构体初始化
如果我们想要在测试数据上做点小变化,可以把两步初始化分开,初始化放在setup()函数中,把每个测试用例微小的数据变化放在各个测试用例中。在应用这个想法的过程中,你可能要创建一些辅助函数,并且你会发现他们实际上应该属于产品代码。
13.6崩溃直到通过
让它能编译 让它能链接 找到运行时依赖 修正运行时依赖 增加更多的C语言遗留代码测试
13.7鉴别测试
可以用测试来捕获当前有价值的行为。如果你对代码理解得好到足以为它写出测试来,你可能对它的理解就足够好到可修改它。
仿制对象能够帮助我们更好的鉴别测试。
13.9测试驱动缺陷修正
当定位缺陷以后,写一个测试来揭示这个缺陷。要抵制住马上去修改缺陷的诱惑。生命是有限的,你不希望在干掉一个正在处理的缺陷时又引入一个新的缺陷。并且我们知道缺陷往往都挤在一起。
13.10增加策略测试
一个有着遗留代码的产品团队应该考虑主动地增加测试来找到已有的缺陷及保护重要的功能。你能花在为遗留代码写新测试上的努力是有限的,因此要有策略。
在遗留代码下工作需要的是一种思想,一种基于我不会引入问题,我会让事情变好的思想。我们会开始偿还技术负债的本金并且减少将来用这些代码时将付的利息。
相关文章推荐
- 测试驱动开发系列之四--代码中的坏味道以及如何改进他们
- 测试驱动开发及代码重构
- 测试驱动开发系列之七--监视产品代码
- 测试驱动开发与代码重构
- mini2440 led驱动代码(原创)基于iomap<测试初始化没有问题,其它功能待开发>
- 优美的测试代码 - 行为驱动开发(BDD)
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(二十二)重构 – 让代码插上翅膀自由飞翔
- 测试驱动开发系列之三--TDD策略:SOLID,灵活并可测试的设计
- 测试驱动开发实践-重构篇
- 测试驱动开发 读书笔记--坏代码的味道
- 测试驱动开发系列之八--测试有合作者的模块
- 测试驱动的开发系列 第一部分:概述(转)
- 测试驱动开发系列之一--嵌入式TDD基础知识
- 测试驱动的开发系列 第二部分:用JUnit测试Java类
- Code maturity level options 代码成熟度选项 [*]Prompt for development and/or incomplete code/drivers 显示尚在开发中或尚未完成的代码与驱动.除非你是测试人员或者开发者,否则请勿选择 我是开发者,所以选[*] Loadable module support 可加载模块支持 [*]Enable loadable module support 内核编译配置选项简介 (2.4.20-8
- 测试驱动开发TDD(四)Google Test系列(目录)
- 测试驱动开发与软件重构
- 穷人如何使用测试驱动开发进行重构
- 测试驱动开发(Test-Driven Development,简称TDD)--单元测试-->提高代码质量
- 测试驱动开发与软件重构