测试先行
我自己造的一些轮子中使用TDD。因为这个花费大量的时间,通常来说测试代码和功能代码的比例可能是 1:1,或者是 2:1 等等。在自己创建的一些个人应用,如博客中,我
不需要与其他人 Share 我的 Content。由于我使用的是第三方框架,框架本身的测试已经足够多,并且没有复杂的逻辑,我就没有对我的博客写测试。而在我写的一些框架里,
我就会尽量保证足够高的测试覆盖率,并且在适当的时候会去 TDD。
通常来说对于单元测试我会采用 TDD 的方式来进行,但是功能测试仍会选择在最后添加进去。主要的缘由是:在写 UI 的过程中,元素会发生变化。这一点和我们在写
Unit 的时候,有很大的区别。div + class 会使得我们思考问题的方式发生变化,我们需要去点击某个元素,并观察某个元素发生的变化。而多数时候,我们很难把握好一个页
面最好的样子。
不得不说明的一点是,TDD需要你对测试比较了解后,你才容易使用它。从个人的感受来说,TDD 是在一开始是一件很难的事。
测试先行
对于写测试的人来说,测试先行有点难以理解,而对于不写测试的人来说,就更难以理解。这里假定你已经开始写测试了,因为对于不写测试的人来说,写测试就是一件
难以理解的事。既然我们都要写测试,那么为什么我们就不能先写测试呢?或者说为什么后写测试存在一些问题?
依据 J.Timothy King 所总结的《测试先行的 12 个好处》:
- 测试可证明你的代码是可以解决问题的
- 一面写单元测试,一面写实现代码,这样感觉更有兴趣
- 单元测试也可以用于演示代码
- 会让你在写代码之前做好计划
- 它降低了 Bug 修复的成本
- 可以得到一个底层模块的回归测试工具
- 可以在不改变现有功能的基础上继续改进你的设计
- 可以用于展示开发的进度
- 它真实的为程序员消除了工作上的很多障碍
- 单元测试也可以让你更好的设计
- 单元测试比代码审查的效果还要好
- 它比直接写代码的效率更高
但是在我个人的感觉里,多比较喜欢的是:写出可以测试的函数。这是一个一直困
越来越大。当我只有一个简单的 IF-ELSE 的时候,我的代码测试起来也很简单:
if (hour < 18) { greeting = "Good day";
} else { greeting = "Good evening";
}
而当我有复杂的业务逻辑时,后写测试就会变成一场恶梦:
if (EchoesWorks.isObject(words)) { var nextTime = that.parser.parseTime(that.data.times)[currentSlide + 1];
if (that.time < nextTime && words.length > 1) { var length = words.length;
var currentTime = that.parser.parseTime(that.data.times)[currentSlide] var time = nextTime - currentTime;
var average = time / length * 1000;
var i = 0;
document.querySelector('words').innerHTML = words[i].word;
timerWord = setInterval(function () { i++;
if (i - 1 === length) { clearInterval(timerWord);
} else { document.querySelector('words').innerHTML = words[i].word;
} }, average);
} return timerWord;
} else { document.querySelector('words').innerHTML = words;
}
我们需要重新理清业务的逻辑,再依据这些逻辑来编写测试代码。而当我们已经忘记具体的业务逻辑时,我们已然无法写出测试。
全站分卷索引 · 119 卷
- 1Growth: 全栈增长工程师指南
- 2软件开发的核心难题:沟通
- 3大公司的专家与小公司的全栈
- 4全栈工程师的未来:无栈
- 5基础知识篇
- 6工具只是辅助
- 7语言也是一种工具
- 8提高效率的工具
- 9IDE
- 10终端或命令提示符
- 11包管理
- 12环境搭建
- 13Windows
- 14GNU/Linux
- 15学好一门语言的艺术
- 16输出是最好的输入
- 17如何应用一门新的技术
- 18Web 编程基础
- 19从 HTML 到页面显示
- 20HTML
- 21中文?
- 22其他 HTML 标记
- 23小结
- 24CSS
- 25简介
- 26样式与目标
- 27更有趣的 CSS
- 28JavaScript
- 29JavaScriptFul
- 30面向对象
- 31其他
- 32前端与后台
- 33后台语言选择
- 34PHP
- 35Model
- 36View
- 37Controller
- 38后台即服务
- 39后台即服务
- 40数据库
- 41搜索引擎
- 42前端框架选择
- 43前台与后台交互
- 44JSON
- 45WebSocket
- 46编码过程
- 47Web 应用的构建系统
- 48Web 应用的构建过程
- 49Web 应用的构建实战
- 50Git 与版本控制
- 51Tasking
- 52Tasking 开发任务
- 53写代码只是在码字
- 54内置索引与外置引擎
- 55内置索引与外置引擎
- 56如何测试
- 57测试替身
- 58Mock
- 59测试先行
- 60可读的代码
- 61命名
- 62函数长度
- 63代码重构
- 64提炼函数
- 65内联函数
- 66查询取代临时变量
- 67重构到设计模式
- 68上线
- 69隔离硬件:虚拟机
- 70隔离操作系统:容器虚拟化
- 71隔离底层:Servlet 容器
- 72隔离依赖版本:虚拟环境
- 73隔离语言:DSL
- 74GNU/Linux
- 75HTTP 服务器
- 76数据库端缓存
- 77前端缓存
- 78运行机制
- 79自动化部署
- 80依赖与包仓库
- 81构建软件包
- 82数据分析
- 83想法-构建
- 84产品-衡量
- 85数据分析
- 86分析数据
- 87用户数据分析:Google Analytics
- 88流量获取
- 89移动应用
- 90网站性能
- 91SEO
- 92什么样的网站需要 SEO?
- 93内容
- 94UX 入门
- 95什么是简单?
- 96进阶
- 97认知设计
- 98持续交付
- 99持续集成系统
- 100持续交付
- 101持续部署
- 102持续阅读
- 103遗留系统与修改代码
- 104遗留代码
- 105修改遗留代码
- 106速度优化
- 107模块重构
- 108Retro
- 109三个维度
- 110架构模式
- 111预设计式架构
- 112演进式架构:拥抱变化
- 113意图导向
- 114重构
- 115模式与演进
- 116相关阅读资料
- 117架构解耦
- 118CQRS
- 119CQRS 结合微服务