我应该如何使用RSpec测试Rails应用程序以获得完整的测试覆盖率?

ror*_*ler 5 ruby rspec code-coverage ruby-on-rails rspec-rails

在为简单的Rails应用编写规范时,以下是完整测试覆盖的正确方法吗?

  1. 为所有用户故事编写功能规范
  2. 编写控制器规范以确保各个操作响应正确并且设置了所有必需的变量
  3. 编写模型规范以确保所有方法,验证,e tc.按预期工作
  4. 写邮件规格
  5. 写路由规范

这是否足够,太多(例如,如果我编写了功能规格,我可以跳过一些较低级别的规范),还是不够?为什么?

Dav*_*uth 5

您不需要为每一层中的每个对象编写规范来获得 100% 的测试覆盖率或测试驱动(要求您实现)应用程序中的所有重要行为。相反,正如行为驱动开发 (BDD) 建议的那样,从外到内编写规范,并仅在必要时编写较低级别的规范。

测试完整性最重要的衡量标准是需求覆盖率:它对于每个用户故事以及每个需要新代码的故事的每个细节都有帮助,至少在一个测试中表示。如果您正在遵循典型的敏捷实践(提及用户故事表明您正在这样做),您的测试可能是您记录需求的唯一地方,因此您可能无法对这种覆盖范围给出数字。拥有它也很有帮助

  • 行覆盖率(大多数人所说的测试覆盖率是指的意思),意味着每一行代码都至少经过一次测试,并且
  • 集成覆盖率,这意味着从一个类到另一个类的每个方法调用都至少经过一次测试。

对于每个故事,

  • 只编写将测试故事的所有独特快乐路径的功能规格。
  • 编写额外的功能规范,以确保集成覆盖快乐路径和悲伤路径的架构上有趣的微小变化。例如,我经常为涉及表单的故事编写三个功能规范:一个是用户填写所有可能的字段并成功,另一个是用户填写尽可能少的信息但仍然成功(确保未指定的值和默认值按预期工作),以及用户犯错误、失败、纠正错误并成功的情况。

此时,您已经测试驱动了每一层(控制器、模型、视图、帮助程序、邮件程序等),仅使用功能规范。

  • 编写模型和帮助程序规范来确定完全存在于这些类中的详细需求。例如,一旦您编写了一个悲伤路径功能规范,该规范规定输入一个特定的无效属性会让用户返回编辑其表单提交并显示一条消息,您可以通过在其中编写更多示例来完全处理其他无效属性模型的规范,用于测试模型属性是否已验证,并让您已经测试驱动的架构将错误传播回用户。

    请注意,虽然您的功能规范已经通过模型和辅助方法测试了快乐路径,但一旦您开始为次要或错误情况的方法编写示例,您可能需要为该方法编写一个或多个快乐路径示例同样,您可以在一处看到该方法的完整描述,因此您只需运行其所有示例即可完全测试该方法,而不必运行任何功能规范。

您可能根本不需要某些规格:

  • 精心设计的控制器操作很短,并且很少或没有条件,因此您通常根本不需要任何控制器规格。仅在需要时编写它们,并保留模型、邮件程序等行为以保持它们简单快速。
  • 同样,视图和邮件程序应该很少或没有条件(复杂的代码应该重构为帮助程序和模型方法),因此您通常根本不需要视图或邮件程序规范。
  • 您的功能规范将测试驱动您需要的所有路由,因此您可能不需要路由规范。只有当我必须对路由进行重大重构时,例如从 Rails 的一个主要版本升级到下一个版本时,我才会使用路由规范。

只要您始终在编写新代码之前编写测试,您将始终拥有 100% 的行覆盖率。


Ste*_*art 1

该测试策略听起来非常全面。如果您完成了所有这些测试,您将获得很大的测试覆盖率。但是,您需要更长的时间才能交付项目。作为进行更有限测试的人,您也不会那么敏捷。测试必须适合项目。不要过度测试。过度测试可能会花费时间和金钱。不要在测试中。测试可能会花费时间和金钱。

有正确的方法来进行单元测试。有正确的方法来进行集成测试。手套必须合适。如果您的应用程序主要面向前端,那么最好从集成测试开始。如果您编写后端应用程序或 API,那么单元测试可能是更好的起点。我认为采用一种测试风格然后扩展到不同的风格是比尝试测试应用程序的每一层更好的开始。

为什么不从简单的单元测试开始呢?它们很容易写。编写这些测试,然后跟踪您发布的错误数量。您是否引入了太多错误?你有很多回归问题吗?是否有一些错误已经进入生产阶段,但您的套件没有发现?如果答案是肯定的,那么也许是时候编写一些更高级别的测试了。请记住,测试级别越高,您需要支付的开发成本就越高。

如果您没有发布错误,那么您就没有理由编写更多测试。请记住这里的最终目标。我们希望发布无错误的代码。如果我们可以单独编写一个测试和一个测试来确保我们正在这样做,那么就没有理由进行进一步的测试。