为什么优秀的开发者喜欢编写测试?
本文最初发表于Typeform 的工程博客。
第一部分: 我的天哪,我彻底疯了!
多年来,我一直听说编写测试的重要性。这也不奇怪,因为这些年来我一直在开发团队中担任质量保证工程师。我听说过单元测试和集成测试的重要性,也了解过测试驱动开发(TDD)的种种好处、代码覆盖率等等,不胜枚举。
敏捷团队和组织一直在谈论它,很长一段时间我都以为它跟我工作无关。虽然它里面有“测试”这个词,但那并不是我参与的那种测试。所以我只是把它记在了我的“好东西清单”里,希望有一天我能明白它为什么会出现在那里。我当时完全摸不着头脑。
与此同时,多年前,我正在学习编程。我当时想转行做开发人员,或者至少是自动化测试人员。像 Codecademy 这样的网站那时才刚刚起步,我疯狂地学习他们的免费课程。不知为何,我一直没注意到练习是如何判断我的代码是否错误的,为什么它们通常能准确地指出代码的哪一部分出了问题。
之后,我参加了一些更密集的“课堂编程课程”。在那里,我学到了一些关于单元测试的目的。单元测试会测试代码中的每个功能单元(或单元格),以确保它能完成所有预期的功能。现在,在多年来我一直没有深入思考这个新定义之后,我突然意识到了一些新的东西:
单元测试不测试面向外部的功能(例如登录表单或端点),而是测试面向内部的功能,确保一段代码可以被其他代码正确使用。
由于我学到了一些新技巧,我也开始做一些小项目,要么是为了应用所学知识,要么是为了挑战自己,开发一些自己想出来的有趣东西。这其中有很多繁琐之处:比如不停地在网上搜索解决方案、不用 Git、搞清楚 CORS 是什么……你懂的。但我的开发流程(或者说缺乏流程)中最糟糕的一点是,我必须对每一个改动都测试每一个用例和各种极端情况。
如果你读到这里,你大概知道我在说什么。要么你现在正经历着,要么你还记得当初开发真正能用的东西时遇到的那种情况。每次逻辑改动后都要手动测试每一个流程变体,那种繁琐的感觉是永远无法忘记的。更糟糕的是,花了三个小时重构之后才发现某个流程出了问题,却完全不知道它是什么时候停止工作的。
现在想象一下,如果所有这些操作都只需在终端运行一条命令,然后看着一大片绿色(偶尔夹杂着红色)的文本展开,那该有多好?当然好,但我还是没能理解。我当时想,我的项目又不是“真正的应用程序”,它们不需要测试。
第二部分: 我以骨头为武器的日子结束了
我在 Typeform 工作大约六个月了。我们团队的测试工作非常独立,不需要我时刻关注测试结果。我们经常进行结对编程和群体编程,我也有机会参与功能开发、变更和修复。这些经历让我受益匪浅,但有一件事总是让我感到惊讶:每当我们完成一项任务,我的队友们都会立刻想要编写测试。这感觉就像是一种本能反应,一种无意识的反射,而不是他们刻意安排的。而他们总是让我措手不及。
那一刻,我往往会感到轻松愉快。事实上,我们已经理解了问题,讨论了解决方案,克服了障碍,最终让系统运行起来了。我只想赶紧喝杯咖啡休息一下,但他们却一心想确保所有测试都覆盖到位。
直到今天,在软件行业工作了近9年后,我才明白其中的原因:
这些人关心代码,而且不仅仅是他们自己编写的代码。他们关心代码的可读性和可维护性,关心代码是否符合良好标准,关心代码是否高效,以及代码是否能够完成其应有的所有功能,无论对内部还是对外。
但是,他们处理的是实际的代码库,这些代码库通常包含大量代码,分布在很多文件中,支持很多功能。而且一天只有24小时。他们需要一种可靠且快速的方法来确保他们的更改生效,更重要的是,确保其他所有功能也都能正常运行。
优秀的开发者喜欢编写测试,因为他们关心代码,并且他们知道(编写良好的)测试是让他们更有信心确保代码正常运行的唯一可靠方法。
他们也知道,如果产品刚开发出来的时候不进行测试,那它可能永远都不会被测试。这也是测试驱动开发(TDD)等方法存在的原因。
使用测试驱动开发(TDD)方法时,首先要为所有需要添加或更改的内容编写测试。没错,我是认真的。在编写实际代码之前先编写测试。当然,所有新测试都会失败,但之后你要编写代码,确保所有测试都能通过。你首先要保证代码覆盖率,然后再构建需要覆盖的功能。
TDD还有一个额外的价值:专注。只有能让测试通过的代码才应该被编写。
尾声: 我希望考试结果能像我梦里那样美好。
最后,我并非想炫耀自己能与优秀的开发者并肩工作,而是想鼓励大家尽早熟悉代码测试。把它变成你工作流程中必不可少的一部分。这并非因为它是行业标准、最佳实践,或者有人说你必须这样做。原因很简单,它无疑会让你的开发工作更轻松、更快乐。
请不要像我一样,有些事情显而易见,却要花好几年才能明白 😉
文章来源:https://dev.to/anabella/why-do-great-developers-love-writing-tests-1o6j