我如何学会喜欢单元测试

2025-05-27

我如何学会喜欢单元测试

时间回溯到2012年。当时我19岁,刚到Village ,还有很多东西要学*,我大概会把自己归类为“黑客”(这曾让Johnny面露苦色,现在回想起来,我能理解)。我喜欢坐在电脑前,开始写功能。设计从我的指尖流淌而出。

当我向我解释单元测试时,我感到一种生理上的厌恶;“这是你必须编写的代码,以证明你的代码有效”……但是谁来测试这些测试呢?

同时,我还接触了“mocks”,它的意思似乎是:“因为不可能用真实数据运行单元测试,所以我们必须看看你的测试代码在非真实数据上运行效果如何。” 这看起来没什么用。

测试痛苦的三重奏是通过鼓励测试驱动开发(TDD)的尝试来完成的,也就是说“你只能编写失败的单元测试的代码,或者使失败的单元测试通过的代码” - 即预先编写所有单元测试,然后编写实现。

这些因素让我内心非常困惑和悲伤,以至于我在专业软件开发的早期没有做太多(成功的)单元测试。

首页 辛普森 GIF - 我的生活被毁了

对我来说,编程曾经是,而且永远都应该是乐趣无穷的!软件开发就像建筑,只不过它拥有无限的撤销、无限的材料、X射线视野和难得元素制成的工具——你可以在眨眼间制造出任何你想要的东西,并随时进行修改。编程富有表现力、充满乐趣、令人满足。而我认为单元测试剥夺了我的这些乐趣。

那么,为什么今天单元测试对我来说是乐趣的一部分呢?

*遗憾的是,从那时起,我要学的东西只增不减

我的第一次单元测试成功

那是2015年。我利用业余时间写了一个游戏,供自己娱乐。在这个游戏中,宇宙飞船可以组建和解散舰队,但这个功能却一团糟。在游戏测试中,舰队会意外组建失败、解散失败、扩张和缩小……我需要找到一种方式来全面测试这些代码路径,而无需亲自以科学严谨的方式逐一测试每个选项。我突然意识到,单元测试才是真正的答案。

一些宇宙飞船的单元测试源代码

我体验到了单元测试的实用性。在这个过程中,我甚至编写了一种简单的模拟程序;它提供一些对象供我使用,而不是用户输入的数据。测试这个项目的过程非常愉快、轻松,因为:

  • 我的项目只能使用普通的旧 .Net 对象(没有数据库连接或奇怪的依赖关系)
  • 被测试的类有明确的职责

测试暴露了我的实现中存在大量缺陷,而这些缺陷即使花费数小时进行手动测试也难以发现。突然之间,代码变得干净、清晰、可控!我还意识到我的游戏逻辑与用户界面紧密耦合;测试无法完成,因为它们在等待用户输入。因此,我重构了游戏对象,使其接受一个委托来推进游戏进程;虽然真实游戏会使用委托Console.Readline(),但测试可以传入一个不执行任何操作的委托。我无意中遇到并实现了控制反转。感谢测试!

加热

个人领域单元测试的成功让我备受鼓舞,于是我开始在 Village 的一个棘手项目中引入测试。这个项目存在一些代码质量问题,团队一直在努力克服。

我们制定了一项政策:每次修复一个 bug,都必须编写一个单元测试来证明它已经修复并且保持稳定!由于我们当时正在集成 Microsoft Office,而某些 Office 对象很难模拟,所以这并不总是可行的。但这鼓励我们:

  • 将业务逻辑与前端集成逻辑分离
  • 测试所有可能的业务逻辑
  • 明确班级职责

这个项目现在有大约300个单元测试,是一个每天都在用户手中运行的成功项目!这是一个很好的机会,让我们快速壮大的团队能够更多地体验单元测试的优势。

让它变得很酷

大约在这个时候,我还注意到 GitHub 上那些拥有数百个 NPM 包的酷小伙子们会自豪地在每个项目的首页上展示自动生成的徽章,上面写着“___% 覆盖率”。他们把单元测试覆盖的代码行比例游戏化了,这很吸引我!

GitHub 仓库首页上的徽章

突然间,单元测试不仅有用,而且很酷。

单元测试注入美感

最近,我们构建了一个搜索多种文件类型内容的项目。不同的搜索组件是独立构建的,因此定期对系统进行全面测试并不现实。这恰恰是单元测试的理想场所,而且该项目已经非常接近测试驱动开发。

  • 搜索提供商遵循工厂模式,通过测试确保它们始终为给定的文件类型生成预期的搜索引擎。
  • 搜索引擎遵循策略模式,并进行测试以确保它们正确读取示例文件。
  • 搜索结果模型的测试非常简单,例如检查新对象上是否始终设置了正确的默认值,或者搜索是否创建了对搜索内容和结果数量的适当描述。

这确实是一件美丽的事物。

有所作为

在某个阶段,单元测试不再是负担,而是乐趣所在。你能做些什么来实现这一点呢?

  • 从简单开始。作为一个企业编程新手,我一下子就接触到了测试、模拟和测试驱动开发 (TDD),这让我不知所措。如果你以前没有做过自动化测试,那就从任何方向开始吧。无论你使用黑盒还是白盒,使用正确的技术还是正确的框架,都没关系。只要测试点东西就行!
  • 掌控它。设计一个你可以测试的简单项目。或者,如果你是一个鼓励者,可以把这个项目交给你的团队,让他们思考。让它充满乐趣。
  • 学习结构。单元测试与面向对象原则密切相关。这需要时间和经验,但随着你对其中一项的改进,你对另一项的掌握也会随之提高。一个大型子程序根本无法测试,但遵循面向对象原则(通常看起来像设计模式)的解决方案将非常易于测试。
  • 让它变得酷炫起来。没错,这有点儿未知。但让倡导者去倡导吧。让你组织里的文化传承者们把它当作一种乐趣的提升,而不是负担。不要反复强调,而是要营造一种氛围,让可证明的品质得到奖励,如果可能的话,最好游戏化!

我希望这篇文章能帮助您了解自动化测试(尤其是单元测试)的优势和便捷性。如果您有任何问题或意见,请在 Twitter 上联系我@SteGriff;如果您想聘请专家机构与您或您的项目合作,请通过@VillageSoftware联系我们!

Village Software联合发布

乔迪竖起大拇指

文章来源:https://dev.to/stegriff/how-i-learned-to-love-unit-testing-29bf
PREV
完整的 Windows Web 开发人员设置指南
NEXT
处理 CORS