在大型Rails应用程序中加速RSpec测试

时间:2010-09-07 21:58:19

标签: ruby-on-rails ruby unit-testing rspec bdd

我的RSpec测试中有一个包含超过2,000个示例的Rails应用程序。毋庸置疑,这是一个很大的应用程序,还有很多需要测试的地方。在这一点上运行这些测试是非常低效的,并且因为它需要很长时间,所以在推动新构建之前我们几乎不鼓励编写它们。我在我的spec.opts中添加了--profile来查找运行时间最长的示例,其中至少有10个平均需要10秒才能运行。在RSpec专家中你是正常的吗?一个例子10秒完全太长了吗?我意识到,有2000个例子,需要花费大量时间来彻底测试所有内容 - 但此时4小时有点荒谬。

你看到你运行时间最长的例子有多少次?我可以做些什么来解决我现有的规格,以找出瓶颈并帮助加快速度。在这一点上,每分钟都会有所帮助。

12 个答案:

答案 0 :(得分:119)

10秒是任何单个测试运行的很长时间。我的直觉是你的规范目标同时运行单元测试和集成测试。这是项目落入的典型事情,在某个阶段,如果您想要更快,更快地生产,将需要克服这种技术债务。有很多策略可以帮助你做到这一点......我会推荐一些我过去使用的策略。

<强> 1。将单元与集成测试分开

我要做的第一件事就是将单元与集成测试分开。您可以通过以下方式执行此操作:

  1. 移动它们(在spec目录下的单独文件夹中) - 并修改rake目标
  2. 标记它们(rspec允许您标记测试)
  3. 理念是,你希望你的常规版本能够快速完成 - 否则人们不会太乐意经常运行它们。所以回到那个领域。让您的常规测试快速运行,并使用持续集成服务器来运行更完整的构建。

    集成测试是涉及外部依赖性的测试(例如,数据库,WebService,队列,有些人会争论FileSystem)。单元测试只测试要检查的特定代码项。它应该运行得很快(可以在45秒内完成9000次),即大部分应该在内存中运行。

    <强> 2。将集成测试转换为单元测试

    如果您的大部分单元测试小于集成测试套件,则会出现问题。这意味着不一致将更容易出现。所以从这里开始创建更多单元测试来替换集成测试。你可以做的事情是:

    1. 使用模拟框架而不是真实资源。 Rspec有一个内置的模拟框架。
    2. 在您的单元测试套件上运行rcov。用它来衡量单元测试套件的完整程度。
    3. 一旦您有一个适当的单元测试来替换集成测试 - 删除集成测试。重复测试只会使维护变得更糟。

      第3。不要使用灯具

      固定装置很邪恶。使用工厂(机械师或工厂女孩)。这些系统可以构建更具适应性的数据图,更重要的是,它们可以构建您可以使用的内存中对象,而不是从外部数据源加载内容。

      <强> 4。添加检查以停止单元测试成为集成测试

      现在你已经有了更快的测试时间,有时间进行检查以阻止这种情况再次发生。

      在尝试访问数据库(UnitRecord)时,会有一些库使用补丁活动记录来引发错误。

      您还可以尝试配对和TDD,这可以帮助您的团队更快地编写测试,因为:

      1. 有人在检查 - 所以没有人变得懒惰
      2. 正确的TDD需要快速反馈。缓慢的测试只会让整个事情变得痛苦。
      3. <强> 5。使用其他库来克服问题

        有人提到spork(加速rails3下测试套件的加载时间),hydra / parallel_tests - 并行运行单元测试(跨多个内核)。

        这应该可以最后使用。你的真正问题在于步骤1,2,3中的所有方法。解决这个问题,你将能够更好地发挥其他基础设施的作用。

答案 1 :(得分:16)

有关改善测试套件性能的精彩食谱,请查看Grease Your Suite演示文稿。

他通过以下技术记录了测试套件运行时间的45倍加速:

答案 2 :(得分:5)

你可以使用Spork。它支持2.3.x,

https://github.com/sporkrb/spork

或./script/spec_server可能适用于2.x

此外,您可以编辑数据库配置(这实质上加快了数据库查询等),这也将提高测试的性能。

答案 3 :(得分:3)

每个例子10秒似乎很长一段时间。我从来没有见过超过一秒的规格,而且大多数都要少得多。你在测试网络连接吗?数据库写?文件系统写道?

尽可能多地使用模拟和存根 - 它们比编写访问数据库的代码更快 。不幸的是,模拟和存根也需要更多时间来编写(并且更难以正确执行)。您必须平衡编写测试所花费的时间与运行测试所花费的时间。

我第二次Andrew Grimm关于查看可能允许您并行化测试套件的CI系统的评论。对于那么大的东西,它可能是唯一可行的解​​决方案。

答案 4 :(得分:2)

上面有几个人提到过Hydra。我们过去曾使用它取得了巨大的成功。我最近记录了加速运行的过程:http://logicalfriday.com/2011/05/18/faster-rails-tests-with-hydra/

我同意这种观点,即不应该使用这种技术来代替编写结构合理且速度快的测试。

答案 5 :(得分:2)

如果您使用的是ActiveRecord模型,则还应考虑BCrypt加密的成本。

您可以在此博文中了解更多相关信息:http://blog.syncopelabs.co.uk/2012/12/speed-up-rspec-test.html

答案 6 :(得分:1)

查看此演示文稿:http://grease-your-suite.heroku.com/#1

答案 7 :(得分:0)

faster_require gem可能对你有帮助。 除此之外,你唯一的方法是(像你一样)配置和优化,或者使用spork或者为你并行运行规范的东西。 http://ruby-toolbox.com/categories/distributed_testing.html

答案 8 :(得分:0)

答案 9 :(得分:0)

提高测试速度有very general video here。可能有帮助。

答案 10 :(得分:0)

如果您还没有尝试过,可以按照一些简单的提示来首先调查大部分时间花在哪里。看看下面的文章:

https://blog.mavenhive.in/7-tips-to-speed-up-your-webdriver-tests-4f4d043ad581

我猜大多数这些都是通用的步骤,无论用于测试的工具如何都适用。

答案 11 :(得分:-3)

删除现有的测试套件。将会非常有效。