单元测试的爱恨情仇,作为码农们,你们写单元测试么?

2022-10-11 19:01:43 +08:00
 tikazyq

作为从事软件开发多年的资深码农,看遍了各种事故和火葬现场。在接触测试驱动开发以及敏捷之后,发现这正是解决 bug 丛生、issue 漫天,最终导致 996 、007 修 bug 的困境。

这里将单元测试的一些看法分享给大家,希望能够提供一些启发。英译版同步发布在 dev.to,欢迎一起交流学习。

下面是正文。


浅谈测试:单元测试的爱恨情仇

引子

"开发安全可靠的应用程序的最好方式,就是不写代码。"--Kelsey Hightower

很多开发者应该或多或少听过单元测试( Unit Tests ),甚至编写过,也或许对其有所了解。不过,在如今瞬息万变的环境下,单元测试似乎正在成为鸡肋。程序员们都知道它的好处,但是对其显得比较冷淡。“进度这么赶,还有什么时间写单元测试呢?”这样的话是不是听着很熟悉?

单元测试是什么?

所谓单元测试,简而言之就是程序员编写测试代码来验证自己写的功能代码是否能按照要求运行。如果测试代码不能通过,就说明自己写的功能代码是有问题的。

这种自己测自己的方式似乎有些可笑,相当于考试时看着答案做题。然而在测试领域,这样的方式有个专业术语叫白盒测试。而白盒测试的对立术语叫黑盒测试,也就是用其他方式来验证。单元测试属于白盒测试,而更高级的测试例如集成测试( Integration Tests )、端到端测试( End to End Tests )、UI 测试( UI Tests ),都属于黑盒测试。单元测试仅仅是测试代码本身。

单元测试有什么用?

单元测试在敏捷开发( Agile Development )中是非常有用的工具。甚至有些敏捷框架,例如极限编程( XP ),就要求每一个功能必须被单元测试覆盖。在之前的文章《浅谈敏捷:你的团队在正确实践敏捷吗?》就提到过单元测试的重要性。

概括来说,单元测试有下面几个重要作用:

因此,表面上来看,单元测试对于软件开发来说会带来比较大的收益。

为什么不写单元测试?

单元测试可以提高我们的产品质量、测试效率,那为什么程序员还是不喜欢写单元测试呢?据 JetBrains 统计,被调查者中仅有 57% 要写单元测试,仅有 35% 会在大部分项目中实施自动化测试。

那么,为什么?有几个可能的主要原因:

然而,这几个原因都经不起推敲:第一,长期来看自己修复 bug 写的代码量肯定远不止这么点;第二,不管是多么牛逼的程序员,代码写多了,根据大数定理,都会有失误的时候;第三,简单功能如果被引用多了,也会变得重要;第四,QA 的主要工作是保证整体质量,而单元测试是保证局部质量,缺陷部件组装出的产品会优质么?

变得有远见

其实,这里最主要的原因是思维模式,程序员大部分时候会站在个体的角度,思考短期的问题,从而忽略了长期的成本收益。作为一个合格的开发者,最主要目标是用最有效的方式开发出最大价值的功能。因此,单元测试在短时间内无法创造价值,从而被很多人忽视。

单元测试就像读书,短期内不能让人知识渊博、名利兼收,但长期来看是会有效果的。单元测试如果成为习惯或组织文化,就会更容易打造高质量产品和持续交付。要在团队中推广单元测试,需要更根本的流程,例如极限编程、测试驱动编程,或者更高决策者,例如 CTO 、架构师。

社区

如果您对笔者的文章感兴趣,可以加笔者微信 tikazyq1 并注明 "码之道",笔者会将你拉入 "码之道" 交流群。

本篇文章英文版同步发布在 dev.to,技术分享无国界,欢迎大佬们指点。

6635 次点击
所在节点    程序员
79 条回复
Twnysta
2022-10-11 20:19:42 +08:00
以前写,但是赶不上业务。然后就都放弃了。
tikazyq
2022-10-11 20:57:28 +08:00
@Twnysta 跟健身一样的,如果不努力就坚持不下去了 hhhh
test4zhou
2022-10-11 20:59:52 +08:00
通用函数会写
learningman
2022-10-11 21:19:38 +08:00
主要是不好拆,函数本身好测,但是要 mock 可太麻烦了
SHF
2022-10-11 22:51:08 +08:00
写 4 年代码到现在,没刻意的写过测试,一般的来说跑起来试一试就能发现问题。在代码中做好 assert 就够了。有写测试代码的时间,不如多想想实现的逻辑,或者在写代码前做好设计。
error101
2022-10-12 00:38:45 +08:00
前端怎么写单元测试比较好
dayeye2006199
2022-10-12 05:44:40 +08:00
之前试过 TDD ,发觉在搞增删查改的时候并没有想象中顺手。
知道我开始写一些框架类代码的时候,才发觉 TDD 的好处。思路非常的自然,先站在用户的角度想别人要怎么使用你的框架,然后写出测试用例,最后去补实现。

这样写出来的框架,质量既稳健,同时又能站在用户的交付思考很多使用难易度的问题,非常的有帮助。
knightgao2
2022-10-12 09:01:01 +08:00
来个前端的 real world 项目,我来学学 TDD 的怎么写
coldmonkeybit
2022-10-12 09:20:16 +08:00
借楼请教一个问题,我是完全没有测试经验的小白,在实际业务中想测试一个接口是怎样写的。
例如一个 post 新增接口,会同时操作几张表,那我每测试一次数据库中就会多几条数据么?
还是会通过其他手段模拟数据呢
tikazyq
2022-10-12 09:49:00 +08:00
@SHF 随时在代码中断言,其实就是一种单元测试的方式,只是断言把单元测试放在了运行时
tikazyq
2022-10-12 09:50:19 +08:00
@error101 前端单元测试可以聚焦于 js 业务逻辑层面,而非视图样式(这个可以通过 UI 测试完成),特别是通用组件,也可以加单元测试
lysS
2022-10-12 09:53:24 +08:00
@coldmonkeybit #9 ut 一般是针对一个函数,你这个太大了。不过非要测也可以,只不过测试环境要数据库,post 完了再读出来看看是否符合期望
wszzh
2022-10-12 09:54:29 +08:00
@coldmonkeybit 用我有限的测试经验回答你,可以建一个测试数据库,使用 flyway 这类软件,测试执行前往测试数据库插入一些测试数据,测试结束清除数据库
tikazyq
2022-10-12 09:57:27 +08:00
@dayeye2006199 是的,经历了社会毒打,才知道来之不易的幸福 hhhhh
Menkou
2022-10-12 10:01:33 +08:00
@error101 可以试试 cypress 可以写组件测试
wolfie
2022-10-12 10:06:30 +08:00
不写,没什么好处,而且大多数人 mvn skip test 都不会。

涉及到升级依赖版本时候,挺有用的。
unco020511
2022-10-12 10:15:16 +08:00
客户端写起来非常非常麻烦,且收益不大
tikazyq
2022-10-12 10:15:40 +08:00
@knightgao2 可以关注微信公众号“码之道”( codao_blog ),后续会有关于前端单元测试的更新
tikazyq
2022-10-12 10:17:24 +08:00
@coldmonkeybit 这涉及到单元测试和更高级一点的接口测试了。就单元测试来说,颗粒度更小,已于操控,如果有依赖的话,可以采用 mock 的方式来解决,因为单元测试只是测试代码本身;接口测试就属于黑盒测试,用 postman 之类的工具就可以了
rodrick
2022-10-12 10:19:23 +08:00
react hooks 之后就不写单测了 难以突出 unit 的概念

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/886162

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX