TDD

TDD,即测试驱动开发,要求先写测试,再写实现。除了日常开发外,其实在做开源贡献时,也非常适合。TDD 要细聊的话,内容可以多到写一本书,甚至还有不同的流派存在。

https://www.zhihu.com/zvideo/1525828011673194496

但是最重要的原则我觉得很简单,那就是:先写测试,再写实现

举个例子

最近又给一个开源项目提了一个 PR,再一次使用了 TDD 大法,正好可以做一个活生生的例子。这次是修一个 BUG,正好可以展示 TDDer 们是怎么修 BUG 的。
https://github.com/xingxingted/koa-to-express/pull/10

别先修,而是先重现

发现了 BUG,千万不要直接修复!注意,直接修复 BUG 其实是在直接写实现代码,这就不是 TDD 了。发现了 BUG,先写个测试用例来重现它,这样当你修复并提交代码之后,cicd 就会运行这个测试用例,从而保证在后续的迭代中同样的 BUG 不会再次出现。

在上一篇文章(https://zhuanlan.zhihu.com/p/542130945)中聊到,由于 Vercel 的函数计算,只默认支持 Express,我为了将自己的陈年老 Koa 项目在 Vercel 的函数计算里复活,就需要将它伪装成 Express,从而使用了一个开源库: koa-to-express。这个库很好用,然而在某个场景下会报错。这个场景就是当引入了 Koa Router 时,如果请求一个不存在的路由,就会报 Internal Server Error。所以先写个用例来重现这个问题:

在测试代码中创建一个 Koa 服务,并使用 koa-router 对一个路由(即 /health)做响应。在具体的测试用例里,故意去请求一个不存在的路由:
image.png

修复

可以看见,对于修复 BUG,其实主要代码往往在写测试用例上。因为最终的修复,就加了一行代码而已:
image.png

提交 PR,等待作者回应

PR 提了几天 了,这个库的作者并没有回应。但是我已经先用起自己修改的版本了,技巧是修改 package.json 对于包的引用方式,详见上一篇文章。

其他例子: Skulpt

image.png
注意:使用 TDD 做开源贡献,并不保证一定能够得到维护者们的采纳。上面的例子,也还是在等待中,希望有好的结果。那为什么拿这个 PR 做例子呢?因为这是一个非常简单并又有代表性的例子,方便让人领会 TDD 修 BUG 的做法。除了这个,我再列举一个自己使用 TDD 做开源贡献并被成功采纳的例子,这是我特别自豪的一个贡献: Skulpt,它可以在浏览器中运行 python。但是我在使用时发现它的中文支持有问题,在进一步研究后,发现其实是所有的 unicode 字符都不能正常显示,于是做了改进的提交: https://github.com/skulpt/skulpt/pull/223,也可以看到,修复本身虽然改动很小,但是测试代码占了大头。

image.png

福利

Skulpt 的维护者们,不仅采纳了这个改动,还把我的名字放在了他们的官网 上,这让我感觉非常自豪。
image.png