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

ran*_*its 90 ruby bdd unit-testing rspec ruby-on-rails

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

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

Blu*_*ish 119

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

1.将单元与集成测试分开

我要做的第一件事就是将单元与集成测试分开.你可以这样做:

  1. 移动它们(到spec目录下的单独文件夹中) - 并修改rake目标
  2. 标记它们(rspec允许您标记测试)

理念是,你希望你的常规构建很快 - 否则人们不会太乐意经常运行它们.所以回到那个领域.让您的常规测试快速运行,并使用持续集成服务器来运行更完整的构建.

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

2.将集成测试转换为单元测试

如果大部分单元测试小于集成测试套件,则会出现问题.这意味着不一致将更容易出现.所以从这里开始创建更多单元测试来替换集成测试.您可以采取以下措施来帮助完成此过程:

  1. 使用模拟框架而不是真实资源.Rspec有一个内置的模拟框架.
  2. 在您的单元测试套件上运行rcov.用它来衡量单元测试套件的彻底程度.

一旦您进行了适当的单元测试以替换集成测试 - 删除集成测试.重复测试只会使维护变得更糟.

3.不要使用固定装置

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

4.添加检查以停止单元测试成为集成测试

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

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

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

  1. 有人在检查 - 所以没有人变得懒惰
  2. 适当的TDD需要快速反馈.缓慢的测试只会让整个事情变得痛苦.

5.使用其他库来克服问题

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

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

  • 我不同意你的第三点,你不应该使用灯具.如果使用得当,它们比工厂更快,因为您不必创建对象.您的数据不必在每个测试用例中创建. (4认同)
  • 关于工厂更快的问题是一个笑话,对吧? (3认同)

mar*_*lly 16

有关改进测试套件性能的精彩手册,请查看Grease Your Suite演示文稿.

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


Ris*_*ogi 5

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

https://github.com/sporkrb/spork

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

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

  • Spork仅用于加速启动,而不是测试.因此,有很多规格,优势是微不足道的. (4认同)