关于本文
作为一名测试顾问,我阅读过大量测试文章。我发现大多数测试文章都比较简单随意,并不值得花费时间去阅读,偶尔能看到一些能帮助阅读者提高编写测试的技巧好文章。本文汇总了这些优秀的文章,并给出了摘要。其中一半的文章是 JavaScript/Node.js 相关的文章 ,另一半文章则适用于各种语言的普遍测试理念。
为什么选择这些文章呢?首先,这些文章写得非常好。其次,这些文章代表“测试新世界”,而不是众所周知的“TDD-ish”,是更现代的概念和工具。
如果你没时间一一阅读,请重点阅读那些标有“🏅 重点必读”的文章!
以下是我汇总的 10 篇测试好文:
1. “选择性单元测试——成本与效益”
✍️ 作者:Steve Sanderson
🔖 摘要:关于“单元”与“集成”的争论一直存在。本文将深入探讨更具体的问题,并通过写这些测试在各种情况下的成本来讨论单元测试的优势。许多人认为测试策略是静态模型,是所有情况下都要编写的测试技术。我们经常听到“总是根据函数来写单元测试”、“主要编写集成测试”这类论点。但是,本文的建议是,单元测试的吸引力应根据每个模块的成本和收益来评估。文章对单元测试净价值高或低的多种情况进行了分类,例如:
如果你的代码很明显,一眼就能看出是做什么的,那么额外设计和验证(例如,通过单元测试)能产生的优势(如果有)就微乎其微了。
本文还使用了一个 2x2 模型,以直观地显示单元测试的优势是高还是低。
题外话:就我个人而言,我(Yoni)总是从组件测试开始,由外而内,首先覆盖高级用户流细节(又称测试钻石)。然后,一有函数,我就会根据其净值添加单元测试。这篇文章在分类和评估单元测试的优势方面对我有很大助益。
👓 阅读时间:9 分钟
🔗 文章链接:https://blog.stevensanderson.com/2009/11/04/selective-unit-testing-costs-and-benefits/
2. “测试实施细节”(JavaScript 示例)
✍️ 作者:Kent C Dodds
🔖 摘要:作者通过一个代码示例概述了测试人员如果在实现细节方面断言必然会导致糟糕的结果。在测试这么多细节的过程中付出的努力暂且不谈,这个方法获得结果总是非“误报正面”即“误报负面”,影响测试的可靠性。该文通过一个前端代码示例来说明这一点,从中得到的经验和教训对任何类型的测试都是普遍适用的。
“避免测试实现细节非常重要,有两个原因。实现细节的测试:
重构应用程序代码时可能会中断。误报负面;
破解应用程序代码时可能不会失败。误报正面;”
p.s. 该作者还有一篇关于现代测试策略的优秀文章——“编写测试,不多,主要是集成”
👓 阅读时间:13 分钟
🔗 文章链接:https://kentcdodds.com/blog/testing-implementation-details
3. 理智测试微服务
🏅 重点必读
✍️ 作者:Cindy Sridharan
🔖 摘要:这篇文章是一篇涵盖了微服务和分布式现代测试的经典文章,文章很长,但非常具有可读性。还记得四年前的冬天,每天睡觉前,我都要在被窝开心地阅读一个小时。我会点开每一个链接,每看完一段就停下来思考,我也有了新的突破。我非常喜欢这篇文章,所以我想专门研究这一领域。几年后,这一领域就成了我工作的主要内容,我很享受工作的所有时刻。
本文首先解释了为什么 E2E、单元测试和解释性 QA 在分布式环境中会表现不佳,以及,为什么任何一种编码测试都不够,还需要一个完备的技术工具箱。该文章介绍了一些大多数开发人员并不熟悉的现代测试技术。其中关键的一部分涉及开发人员的典型测试技术:作者提倡“大单元测试”(即组件测试), 因为它是开发人员的舒适度和现实之间的一个不错的平衡。
我套用了“阶跃测试(step-up testing)”这个术语,其总体思路是在一般测试之上再测试一层。在这种模式下,单元测试看起来像集成测试(将 I/O 作为被测单元的一部分,在一定范围内进行),集成测试看起来更像是针对实际生产的测试,而生产中的测试看起来更像监控和探索。分布式系统重组后的测试金字塔(测试漏斗)看起来如下:
无论你使用什么类型的系统,这篇文章都将拓宽你的测试视野,让你了解许多好用的新理念。
👓 阅读时间:2 小时以上
🔗 文章链接:https://copyconstruct.medium.com/testing-microservices-the-sane-way-9bb31d158c16
4. 如何使用 Node.js 进行单元测试?(JavaScript 示例,适合初学者)
✍️ 作者:Ryan Jones
🔖 摘要:推荐给初学者。本文中的其他文章都是关于高级测试,只有这篇文章是为测试初学者准备的。
之所以从众多备选教程中选择这个教程,是因为它写得很好,也相对全面。它涵盖了初学者应该首先学习的第一步“kata”:测试解剖语法、测试运行器 CLI、断言(assertion)和异步测试。不言而喻,这些知识还不足以覆盖真实世界中的应用程序测试, 但它能让你安全地进入下一阶段。我个人的建议是:读完这本书,然后学习测试替身(模拟)。
👓 阅读时间:16 分钟
🔗 文章链接:https://medium.com/serverlessguru/how-to-unit-test-with-nodejs-76967019ba56
5. “对单元测试的痴迷”
✍️ 作者:Martin Sústrik
🔖 摘要:文章开篇写道,“我听说现在很多人都想写单元测试。如果你也想写,不妨先花几分钟时间想想不写单元测试的理由”。但是,该文章并不反对单元测试,而是强调单元测试的不足之处。在单元测试效果不佳的情况下,就应考虑使用其他技术。例如:单元测试本身的投资回报率较低,作者使用了一个形象的比喻:如果你在粉刷房子,你想一开始就用最大的刷子,最后用小刷子处理细节。如果你的 QA 工作一开始就使用单元测试 ,就相当于用质量上乘的毛笔来粉刷整个房子......
👓 阅读时间:5 分钟
🔗 文章链接:https://250bpm.com/blog:40/
6. “模拟是一种代码异味”(JavaScript 示例)
✍️ 作者:Eric Elliott
🔖 摘要:这里的大多数文章都属于“现代测试浪潮”,本文则更为“经典”,适合 TDD 爱好者或任何需要写单元测试的人。本文将介绍如何减少测试中的模拟(测试替身)次数。这不仅是因为模拟是测试编写中的一项成本,还因为模拟会提示错误。换句话说,模拟并不代表绝对错误且必须立即修复,但是多次模拟代表着效果不理想。试想一下,一个从许多其他模块那里继承的模块,或者一个会聊天的模块,它需要与少数其他模块协作才能完成工作,那么测试和更改这种结构就会让人感觉“压力山大”:
“我们的 decomposition 策略失败时,需要进行模拟。”
作者使用各种技术来设计自主性更强的单元,例如通过将副作用与程序逻辑的其他部分隔离来使用纯函数、使用 pub/sub、隔离 I/O、使用单体组合等模式来组合单元等。
文章的整体基调很平稳。作者在文章中鼓励使用远离主流的函数式编程和技术,在阅读这几部分时,可以多慎重考虑。
👓 阅读时间:32 分钟
🔗 文章链接:https://medium.com/javascript-scene/mocking-is-a-code-smell-944a70c90a6a
7. “为什么优秀的开发人员会编写糟糕的单元测试?”
🏅 重点必读
✍️ 作者:Michael Lynch
🔖 摘要:我非常喜欢这篇文章。作者举例说明了有时开发人员怀着美好的愿望却写出了糟糕的测试:
软件开发人员常常以错误的思维方式进行单元测试,他们机械地套用在生产代码中学到的所有“规则”,不检查这些规则是否适用于测试,导致最后把摩天大楼建在了沙滩上。
作者采用具体的代码示例,展示了一旦我们运用“天马行空”的思维,测试的可读性下降,以及如何保持简单。在其中一部分中,他演示了如何正确的违反 DRY 原则,让读者存在于测试中,同时让代码可维护。这篇文章能极大地改进那些倾向于编写复杂测试的开发人员的观念。如果你的团队中有这样的人,一定要把这篇文章转发给他。、
👓 阅读时间:11 分钟
🔗 文章链接:https://mtlynch.io/good-developers-bad-tests/
8. “2022 年 JavaScript 测试概述”(JavaScript 示例)
✍️ 作者:Vitali Zaidman
🔖 摘要:本文的特别之处在于,它梳理了几乎所有的 JavaScript 测试工具。可以帮你丰富“工具箱”。例如,如果你知道有一些集成开发环境扩展可以在代码中直接显示覆盖率信息,这可能会帮助你提高测试的采用率。了解可靠、免费和开源的可视化回归工具,可能会激励你涉足这一领域,举几个例子。
“我们概述了网络开发社区中最流行的测试策略和工具,希望能帮你更轻松地测试网站。总体来说,通过了解活跃的开发人员社区中流行的一般模式,并将其与你自身的经验和应用程序的特点相结合,才能作出应用程序架构的最佳决策。”
作者还很贴心地写出了大多数工具的优/缺点,以便读者能快速了解各种工具的相互关系。文章涵盖的类别包括断言库、测试运行器、代码覆盖工具、可视化回归工具、E2E 套件等。
👓 阅读时间:37 分钟
🔗 文章链接:https://medium.com/welldone-software/an-overview-of-javascript-testing-7ce7298b9870
9. 安全的生产测试
✍️ 作者:Cindy Sridharan
🔖 摘要:“在生产中测试”听起来非常冒险,即在生产过程中进行测试,而不是事先验证交付(另一个糟糕的测试术语)。实际上,“生产中测试”并不能取代“编码时测试”,只是在部署、发布和发布后这三个阶段进行安全测试来加一层保险。这篇文章涵盖了数十种技术,其中有些技术非常罕见,如流量阴影(traffic shadowing)、轻敲比较(tap compare)等。更重要的是,它阐明了完整的测试工作流程,从开发人员机器到在生产中为用户服务的新机器,在整个过程中逐步建立信心。
我越来越相信,测试环境就像模拟器,最多只是对真品的模仿。
在“试运行时能用”比“在我的机器上能用”好不了多少。
👓 阅读时间:54 分钟
🔗 文章链接:https://copyconstruct.medium.com/testing-in-production-the-safe-way-18ca102d0ef1
10. 请不要使用模拟(JavaScript 示例,来自 JSConf)
🏅 重点必读
✍️ 作者:Justin Searls
🔖 摘要:这段精彩的 YouTube 视频讲述了测试的致命弱点:究竟在哪里模拟。测试范围在哪里结束,哪些应该模拟,哪些不应该模拟,这大概是最具战略性的测试设计决策。例如,模块 A 与模块 B 交互。如果通过模拟 B 来隔离 A,那么即使 B 的接口发生了变化,A 的代码没有跟上,A 的测试也会一直通过,因此,A 的测试高度稳定,但生产将在数小时内失败。Justin 在演讲中说,
“从未失败过的测试是糟糕的测试,因为你从中什么也没有学到。测试的目的就是失败。”
随后,他还以精美的视觉效果和大量的见解来探讨许多其他有趣的模拟,一定不要错过!
👓 阅读时间:39 分钟
🔗 文章链接:https://www.youtube.com/watchv=x8sKpJwq6lY&list=PL1CRgzydk3vzk5nMZNLTODfMartQQzInE&index=148
其他资源
- Property-Based Testing for everyone
- METAMORPHIC TESTING
- Lean Testing or Why Unit Tests are Worse than You Think
- Testing Strategies in a Microservice Architecture
- Test Desiderata
- TDD is dead. Long live testing
- Test-induced-design-damage
- testing-without-mocks
- Testing Node.js error handling
原文作者:Yoni Goldberg
原文链接:https://practica.dev/blog/a-compilation-of-outstanding-testing-articles-with-javaScript/