编写可测试js
先前参加了D2,其中天猫的不四
在 用 Node.js 构建海量页面渲染服务
分享中,关于稳定性提到并重复三次的一个事情就是:单元测试
之前做项目的时候,也曾经使用mocha写一些单元测试,开始写了部分接口单元测试后,就没再坚持下去。至于为什么没坚持下去,后面我再分析。
但是打从心底觉得,单元测试是开发中很重要的一环,乘着年前稍微空闲,总结一下对于单元测试的一些想法。
为什么没坚持
回想先前的一些项目的情况:一开始,下很大决心,准备完善的编写测试,可是写着写着,就没坚持下来,这是为啥呢?
分析原因有几个:
费时间,拖进度
单元测试往往会占用一半或以上开发时间,从开发感觉上,就会自己进度变得缓慢,心里有点慌,就没继续写下去了
有时候觉得很傻逼
有时候一些接口比较简单,写的过程,就会觉得,我明知道这个代码的执行结果(输出)了,还写这个测试代码?有意义吗?
无法模拟真实环境
有时候,有些代码,运行在webview下或者接口依赖于内部的某些api,模拟环境依赖于mocha这些库很难做到,这时候,要写单元测试起来,就很麻烦了
于是,干脆就算了~~ ̄□ ̄||
不清晰应该测试哪些内容
我们都知道,单元测试,在于构造一些场景出来,作为输入条件,然后最终期待正确的接口,这里就涉及到一个场景构造的问题,一个接口对外暴露给别人使用,
我们就得预测各种场景,所以一个非常简单的函数,就得构建不少的场景,心里会有一堆堆的场景出现,
- 参数A未传的情况,参数B未传的情况~~
- 上下场景不存在的情况
- 参数缺失要不要做处理
- 数据类型要不要验证下,要不要判断,转换一下?
- 。。。
一个简单函数,得写多少个单元测试,心里压力就上来啦1
#### 部份代码无法测试
先前的项目,基本上是用seajs ,匿名闭包 或 commonjs 进行模块化,只能对对外暴露的接口进行测试,测试范围有限。在没了解`rewire` 或 `jest`
之前,觉得单纯测试接口,效果不大,呵呵呵~~那就算了~~
总结为什么没坚持下来,就两个字:
```
麻烦
```
## 为什么还得坚持
分析了之前为啥没坚持,的确麻烦,真心麻烦,构造场景,写单元测试,改源码,再测,再改
但是,纵观各个编程语言,无不强调单元测试的重要性,更有甚者(golang
),直接集成单元测试相关的库,可见在质量保障上的地位。
坚持下去肯定是必须的,它会给我们带来什么好处?
信心
信心源自于对代码的掌控,对代码的把握在于单元测试。有完善的单元测试,能够建立起对项目代码的信心。毕竟,这些代码都通过了单元测试,
预料之中,预料之外的情况,都做了考虑,无需担忧。
撸棒性
程序的稳定,在于不同场景下,能够经得起折腾,不轻易down机,这就需要我们单元场景中,多考虑各种情况,编写代码解决这些情况,
遇到问题,解决问题的同时,编写对应的单元测试,不断完善测试覆盖面
可维护性
程序员最讨厌的事情,就是维护别的系统。但却是大部分人工作的主要内容,如果有幸参与从零开始的项目,为了防止被后人骂得太厉害,单元测试还是写一下吧。
为什么要写呢?单元测试其实就是示例,当人家看不懂代码时,看看你的单元测试,大概就可以猜测出,你的函数、接口是干嘛用的了。
同时,当别人改你代码时候,可能并不是通读整个系统代码,就开改了,这时候,单元测试就保障了你的程序,不会被改坏~~
如何做好单元测试
既然好处多多,那么接下来聊聊怎么才能写好单元测试
编写可测试代码
首先考虑到单元测试的同学,对代码质量要求肯定不低,下面整理了一个思维导向图,主要描述如何才能保证产出的代码有一定得可测试性。
总之一句:编写优雅代码
, 让阅读你代码的人,觉得是件赏心悦目的事情,而不是煎熬。
![[现值] [现值]](/2016/02/03/write-testable-js-code/mindmap.png)
单元测试工具选型
最近总结部门内部使用的公用库,用到技术栈为: karma + mocha + chai + rewire + phantomjs
,仅供参考,这里想说一下,
不要纠结于选什么测试库或者runner,选一个你熟悉的就可以开始干活,没用过的话选一个github上star多的
- karma 是一个test runner,配置简单,插件丰富,不需要你写静态脚本
- mocha 单元测试库
- chai 断言库
- rewire 依赖注入库
- phantomjs 用于CI服务器自动测试使用
rewire 是一个非常不错的依赖注入库,上面提到的部份代码无法测试
问题,通过这个库轻松的解决,类似的还有facebook出品的jest
单元测试原则
首先,单元测试行覆盖率越高越好,但是也无需过滤纠结那个数字。当你做的是一个业务项目,能够覆盖基本的场景就可以了,对于公用库,
则需要提高一定得覆盖率,大家一看你测试覆盖率90%以上,用起来也有信心。
如果写业务代码,考虑基本的场景就可以了,代码进行相应处理,不用过于杞人忧天,考虑非常多不可能出现的情况,代码也不至于过于罗嗦和臃肿。