在大型Rails应用程序中加速RSpectesting
我的RSpectesting中有超过2000个示例的Rails应用程序。 不用说,这是一个很大的应用程序,还有很多需要testing的东西。 在这一点上运行这些testing是非常低效的,因为它需要这么长时间,所以在推新版本之前,我们几乎处于不鼓励写它们的地步。 我在spec.opts中添加了-profile来查找最长的运行示例,其中至less有10个平均需要10秒才能运行。 RSpec专家是否正常? 例如10秒完全太长了吗? 我意识到,用2000个例子来说,要彻底地testing所有的东西需要花费不小的时间 – 但是在这一点上4个小时是有点可笑的。
什么样的时候你看到你最长的例子? 我能做些什么来排除现有的规格,以便找出瓶颈并帮助加快速度。 现在每分钟都会有帮助。
对于任何单个testing运行10秒是非常长的时间。 我的直觉是你的规格目标同时运行单元和集成testing。 这是一个典型的项目,在某个阶段,你需要克服这个技术债务,如果你想生产更多,更快。 有很多策略可以帮助你做到这一点…我会推荐一些我以前用过的。
1.从集成testing中分离出单元
我要做的第一件事就是将单元从集成testing中分离出来。 你可以这样做:
- 将它们移到(在spec目录下的单独文件夹中) – 并修改耙机目标
- 标记它们(rspec允许你标记你的testing)
哲学是,你希望你的定期build设是快速的,否则人们不会太乐意经常运行它们。 所以回到那个领域。 让您的常规testing快速运行,并使用持续集成服务器来运行更完整的构build。
集成testing是一个涉及外部依赖的testing(例如数据库,WebService,队列,还有一些会争论FileSystem)。 unit testing只是testing你想要检查的特定代码项目。 它应该运行得很快(在45秒内有9000个是可能的),即大部分应该在内存中运行。
2.将集成testing转换为unit testing
如果你的unit testing的大部分小于你的集成testing套件,那么你有一个问题。 这意味着不一致将更容易出现。 所以从这里开始创build更多的unit testing来取代集成testing。 在这个过程中你可以做的事情是:
- 使用一个模拟框架,而不是真正的资源。 Rspec有一个内置的嘲笑框架。
- 在你的unit testing套件上运行rcov。 用它来testing你的unit testing套件是多么彻底。
一旦你有一个适当的unit testing来取代一个集成testing – 删除集成testing。 重复的testing只会使维护变得更糟。
3.不要使用灯具
灯具是邪恶的。 使用工厂(机械师或factory_girl)。 这些系统可以构build更多的适应性数据图表,更重要的是,它们可以构build可以使用的内存对象,而不是从外部数据源加载内容。
4.添加检查以停止unit testing成为集成testing
现在你已经有了更快的testing,有时间进行检查,以防止这种情况再次发生。
有猴子补丁活动logging试图访问数据库(UnitRecord)时抛出错误的库。
你也可以尝试配对和TDD,这可以帮助你的团队写更快的testing,因为:
- 有人在检查 – 所以没有人懒惰
- 正确的TDD需要快速反馈。 缓慢的testing只是让整个事情变得很痛苦。
5.使用其他库来克服这个问题
有人提到spork(加速rails3下testing套件的加载时间),hydra / parallel_tests – 并行运行unit testing(跨多个核心)。
这可能应该用到最后。 你真正的问题是在步骤1,2,3中完成的。解决这个问题,你将能够更好地扮演更多的基础设施angular色。
有关提高testing套件性能的优秀教程,请查看Grease Your Suite演示文稿。
他通过利用以下技术在testing套件运行时logging了45倍的加速:
- fast_context
- quickerclip
- 水螅
- 可怕的文件系统调整
- tcmalloc
- Ruby Enterprise Edition GC调优
你可以使用Spork。 它支持2.3.x,
https://github.com/sporkrb/spork
或./script/spec_server可以为2.x工作
你也可以编辑数据库configuration(这本质上加快了数据库查询等),这也将提高testing的性能。
每个例子10秒似乎是一个很长的时间。 我从来没有见过一秒钟以上的规格,而且大多数要less得多。 你在testingnetworking连接吗? 数据库写入? 文件系统写入?
尽可能多地使用mock和stubs – 它们比编写碰到数据库的代码要快得多。 不幸的是,嘲笑和残留也需要更多的时间来写(而且难以正确)。 你必须平衡写testing的时间和运行testing的时间。
我第二次安德鲁·格林 ( Andrew Grimm )关于查看一个CI系统的评论,这个系统可能允许你并行化你的testing套件。 对于大小的东西,这可能是唯一可行的解决scheme。
结帐这个演示文稿: http : //grease-your-suite.heroku.com/#1
上面有几个人提到了Hydra。 过去我们用得很成功。 我最近logging了hydra启动和运行的过程: http : //logicalfriday.com/2011/05/18/faster-rails-tests-with-hydra/
我同意这样一种观点,即不应该用这种技术来代替编写结构合理,缺省速度快的testing。
如果您使用ActiveRecord模型,则还应该考虑BCryptencryption的成本。
你可以在这篇博文中阅读更多关于它的内容: http : //blog.syncopelabs.co.uk/2012/12/speed-up-rspec-test.html
faster_require创业板可能会帮助你。 除此之外,你唯一的方法就是(像你一样)进行configuration和优化,或者使用spork或者其他可以同时运行你的规格的东西。 http://ruby-toolbox.com/categories/distributed_testing.html
这里有一个非常一般的video来提高你的testing速度。 可能有帮助。
您可以按照一些简单的技巧来首先调查大部分时间花费在哪里,如果您还没有尝试过。 看下面的文章:
https://blog.mavenhive.in/7-tips-to-speed-up-your-webdriver-tests-4f4d043ad581
我想大多数这些都是通用的步骤,无论用于testing的工具都可以应用。
删除现有的testing套件。 将是非常有效的。