我学到的关于测试 React 应用的知识 - 单元测试单元测试测试行为,而不是实现重构不应该破坏测试

2025-06-10

关于测试 React 应用,我学到的知识 - 单元测试

单元测试

测试行为,而不是实现

重构不应该破坏测试

开始之前,我正在开发https://cloudash.dev,这是一种监控无服务器应用的全新方式🚀。如果你在调试生产事件时厌倦了在 50 个 CloudWatch 选项卡之间切换,可以看看这个。


在软件开发方面,只有一件事是可以绝对肯定的——最终会出现问题。

无论您拥有多少年的经验,使用什么框架,团队结构等,您都会在生产中遇到错误(前提是您没有将基本的待办事项应用程序作为服务提供)。

好消息是,编程有点像电子游戏。你进步越大,面临的问题就越难,而回报(也就是用户的幸福感)也会越来越大。

这就是为什么测试在发布一款重要的软件时如此重要。有时候,你甚至根本不可能通过“点击”应用程序来查看一切是否正常。

测试有几种类型——最主要的是单元测试、集成测试和端到端测试。为了方便起见,我想将单元测试和集成测试统称为“单元测试”(请正在阅读本文的QA工程师们原谅我)。我个人的区分如下:

  • 单元测试是开发人员关心的测试
  • e2e 测试是用户关心的测试(稍后将在第 2 部分中详细介绍)

单元测试

编写单元测试很棘手,因为你可以给它们设定一个数字。追求这个神奇的数字可能会让你误入歧途。这个数字当然就是测试覆盖率

不要试图实现 100% 的测试覆盖率

你很可能会得到这样的结果:

一张儿童字母玩具的图片,上面每个字母都放错了位置

我的意思是,从技术上来说它是 100%,对吧?

追求测试覆盖率与追求质量不同。

我个人的建议是,尽量达到大约 70-80% 的单元测试覆盖率,同时维护一份详尽的“亲爱的覆盖率工具,请忽略该文件”列表。你肯定不想让那些没有被单元测试覆盖的区域设置或配置文件“污染”你的结果。

一般来说,作为代码库的所有者,你至少应该清楚哪些部分你没有测试以及原因。我们并非完美,有些代码很难用单元测试覆盖,有些情况时有发生(这时我建议尝试用端到端测试来测试系统的这部分)。

还有一件事——确保你的测试可以失败。我一次又一次地编写了测试(尤其是异步测试),它们总是能通过。这很棒,除非你考虑到当我直接删除我试图测试的函数时,它们也会通过。学到了什么?先从一个失败的测试开始,然后确保它能够通过并给你带来价值。

测试行为,而不是实现

让我问你一件事:谁在乎你是否为你所在州的某个地方命名disableAwesomeButton

最有可能的是你,也可能是你的团队,但除此之外呢?没人关心。用户不关心[需要引用],你的测试也不应该关心。

编写如下测试可能很诱人:“当我点击这个按钮时,我期望组件的状态变为 X,并且传递给子组件的 props 应该等于 Y”。这就是最终导致测试变得脆弱的原因。

有人重命名了 props,或者修复了 state 字段的拼写错误,结果程序就崩溃了。你肯定不希望发生这种情况

幸运的是,有一个很棒的工具可以提供帮助:React Testing Library。过去几个月我一直在亲自使用它,虽然需要一段时间才能适应(尤其是在像我一样使用了多年的 Enzyme 之后),但它的好处是巨大的。

使用 React Testing Library 编写客观上糟糕的测试真的非常困难,因为它在构建时就考虑到了最佳实践。例如,我不太确定如何使用 React Testing Library 编写一个检查组件状态是否等于 X 的测试。

测试的是组件的行为。

  • 我们向用户展示的内容是否正确?
  • 是否可以通过alt文本查找图像?
  • 我们呈现的错误信息是否正确?
  • 组件对点击和其他事件的响应(React,懂吗?)是否正确?我所说的“正确是指“组件的行为是否符合用户的预期?

默认情况下,React Testing Library 不会浅层渲染你的组件。这意味着,如果你渲染一个Menu组件,它也会完全渲染MenuItem其下的所有组件。

这使您可以测试菜单的实际行为,而不是检查“好吧,<MenuItem/>我的树中有 5 个组件,我在这里完成了”。

重构不应该破坏测试

这种方法非常好,因为它允许您做另一件事:根据需要重构您的组件。

真实情况:React Hooks 发布时,我们很难在代码库中采用它们,因为(截至 2019 年 10 月)我们使用的测试库 Enzyme 不支持 Hooks。更不用说我们的测试有点过于注重实现。

当你切换到不测试实现的方法时,你可以在组件中做任何你想做的事情。你可以将其重构为 hooks、类、jQuery——只要行为(你懂的,用户关心的东西)不变。

即使重构会导致测试失败,这也是一个重新审视的机会。也许它们失败的原因很充分?重构很困难,很有可能会破坏某些功能。一如既往,让测试告诉你这些,比让用户告诉你要好。

测试不仅是为了用户,也是为了我们开发者。为了我们自身的心理健康,在重大重构后所有测试都通过会让我们感觉良好。正如我之前提到的,你将无法“点击”整个应用程序,所以“所有测试都通过,将其发送到生产环境,yolo”的提醒信息确实很有帮助。

嗯,实际上有一种方法可以点击你的按钮和其他东西,但我会写一篇关于cypress.io 的单独文章




以上内容对您有帮助吗?欢迎在 Twitter 上联系我,我的账号是@tlakomy​​链接:https://dev.to/tlakomy/what-i-ve-learned-about-testing-react-apps-part-1-55g7
PREV
面向 JavaScript 开发人员的十大 GitHub 存储库🚀
NEXT
“糟糕,我把生产搞坏了”——我们如何确保不再发生这种情况?实施变革