在 Ruby 社区中你会听到很多人说:“测试很重要”。但是并没有给出很好的理由。
如果你是从其他的语言转到 Ruby 语言的,你会立刻注意到,由于 Ruby 语言自身 的 Duck 类型,Ruby 是一门非常宽容的语言。这是一件好事,因为你可以快速证 明一个概念而无需担心面前的所有细节,但是,这也是一件坏事,由于 Ruby 语言 的宽容性,基于此写出来的代码通常很不完美。
关键是要意识到你在做什么,并为当前的任务选择合适的工具。测试正是这些工具 中的一种。它使你能够写出更好的代码,同时也为代码提供文档。
如果你正在构建面向客户的应用,你可能希望编写能够持续多年的代码。我不是说 你会把程序放在那里,再也不碰它。我的意思是,代码很容易被改变,以适应频繁 变化的市场需求。
我确信你已经看到了 Ruby on Rails 框架自带的很多测试类型,你可能想知 道,为了能够编写生产环境的应用,你是否需要学习所有这些测试类型,答案即是 又不是。
它们都只适合两种测试。集成测试和单元测试。
通过集成测试,你的目标是模拟一个真实的场景,在这个场景中,许多代码单元通过协作交付一些价值。另一个观察点是,确保所有的代码单元都作为一个整体一起工作。这是因为虽然每个单元都可以独立运行,但它也必须与其他单元正常协作。
单元测试确保每个代码单元在隔离状态下都能正常工作。这样做的原因是,如果每 个单元都正确地完成了任务,那么就很容易将代码单元组合起来 (就像乐高积木一 样),从而创建一个应用程序。
因为你会经常遇到这些名字,让我们看看它们是什么意思,以及你应该如何使用它 们。
通过功能测试,你就像一个真正的用户一样,通过与应用交互来测试应用程序。 所以功能测试是集成测试。
用户点击链接、按钮、填写表单、与弹出窗口交互等等。
功能测试都是关于用户能看到的东西。
他们会给你最大的回报 -- 确保你的用户从你的应用中获得价值。或者从另一个角 度来看,你正在确保应用程序不会以用户可能注意到的方式挂掉。
因为功能测试需要尽可能多地模仿用户的行为,并且尽可能地使用 web 浏览器来完 成用户的工作,这是非常慢的,这也是功能测试最大的缺点。
请求测试是以端对端的方式测试你的应用,但是他们关注的是用户看不到的东 西。例如:被添加到数据库中的记录,或者关于 HTTP 请求状态码的断言,重定向, 调用第三方 api 等等。
请求测试都是关于用户看不到的内容。
因为你不是用浏览器来驱动这些测试,所以它们比功能测试要快得多,但是仍然有 点慢,因为它们必须针对数据库进行查询。
通过单元测试,你的目标是深入到每一个业务逻辑中,并确保它在你所能想到的每个上下文中都能正常运行。
单元测试涉及领域逻辑和边界情况。
它们的速度也非常快,如果你写的单元测试与其他东西 (比如:其他对象,或 者 Rails 框架) 是隔离的,那么你就能从测试中得到即时的反馈,这纯粹是一种乐 趣。有了即时反馈,并依靠测试来告诉你下一步要去哪里,因为你不必把所有的内 容都放在脑子里,所以这也使得写代码变得容易多了。你可以安全地将其委托给你 的测试。
不同类型测试的优缺点:
类型 | 优点 | 缺点 |
---|---|---|
功能测试 | 确保你的应用在用户使用时不会挂掉 | 非常慢 |
请求测试 | 你的应用在后台能够正常工作 | 有点慢 |
单元测试 | 你的应用可以处理边界问题 | 不能保证所有的代码在一起正常的工作 |
在 Ruby on Rails 应用中使用不同类型的测试,在一定程度上是一种平衡行为,你需要对覆盖范围和速度进行权衡。你希望你的整个测试套件能够快速运行,这样你就可以经常运行它,并且你希望你的应用程序能够进行彻底的测试,这样就可以更容易地进行更改。