我正在运行mysql,database_cleaner,Rspec等。到目前为止,我有大约518次测试,它们需要88秒才能运行。这对我来说是不可接受的,因为我的应用程序开发刚刚开始。
因此,在进一步研究之前,我想尝试找到减少运行这些测试所需时间的方法 - 希望无需实际更改测试。
在大多数情况下,我正在尝试使用存根。但是,当我测试模型和查询时,我确实使用了数据库。
我认为database_cleaner正在减慢它们的速度,但我不知道如何在没有它的情况下测试查询和内容。
将sqlite3与“:memory:”选项一起使用似乎只能减少约10秒钟(令人失望的结果......)
如何才能真正加快测试速度?
答案 0 :(得分:17)
您可以使用各种策略来加快测试时间。如果你刚开始,并且你看到88秒的运行时间,我会想到很多这些适用于你:
答案 1 :(得分:5)
我没有提到工厂女孩,因为我没想提到它(不要问)。事实证明这是非常相关的细节,因为它负责测试运行如此缓慢。
通过简单地从我的控制器测试(我使用Factory.build
)中删除Factory girl,我已经设法将它们从50秒缩短到类似5的东西。
原因是Factory.build
调用Factory.create
进行关联,导致数据库命中...所以如果你有很多关联,那么创建一个新的模型对象需要一段时间。但更重要的是,在我的案例中,这仅占开销的30-35%。 Factory_girl实际上花费了65-70%的时间来做非数据库的事情。我不知道为什么,但在强制每次调用Factory.build
之后,构建我的对象仍需要很长时间。使用基本MyClass.new
最终会更快很多。
我的整个测试套件现在需要不到30秒而不是90秒。通过进行这些改变,这通常会增加300%的速度......但是当谈到控制器测试时,我的速度提高了2000% - 而且我已经踩到了!所有这些性能开销都归因于Factory.build
!这就是大部分收益来自的地方。
当然,我回到了我的模型中,无论身在何处,我都会使用Factory.build
或MyClass.new
。
我也尽可能在:default_strategy => :build
添加了factories.rb
,以防止Factory Girl进入数据库。如果你问我,这应该是默认值,因为这次更改只有1次测试失败了,但是我通过这个改变设法从模型测试中得到了10秒。
如果您遇到类似我的问题,请按照以下步骤进行操作,您应该注意到速度提高2-3倍并且没有太大的缺点。
答案 2 :(得分:3)
我一直在使用以下hack来减少在垃圾收集器中花费的时间:
http://makandra.com/notes/950-speed-up-rspec-by-deferring-garbage-collection
文章提到了15%的改进,但在我的测试中,我看到使用Ruby 1.9.2,Rails 3.0.x和RSpec 2.0的比例约为25%。
此外,如果您不使用自动测试,这可能有所帮助,因此您只对已更改的代码运行测试。
最后,尝试使用RSpec“--profile”选项来识别10个最慢的例子,看看你是否可以优化最坏的罪犯的表现;在我的一个项目中,我发现只有3个测试将测试执行时间增加了一倍,因此我对其进行了“修复”,并将整个测试套件恢复到可接受的时间范围。
答案 3 :(得分:0)
您是否需要一直运行所有测试?您可以为不同的测试集设置rake任务,并运行与您最近更改的应用程序部分相关的任务。当然,大多数测试都会运行在没有改变的代码上。然后,每隔一段时间你就可以运行全套规格,以确保一切兼容。无论如何,这似乎是最简单的解决方案。
答案 4 :(得分:0)
我认为如果在RSpec中启用use_transactional_fixtures,则根本不需要使用database_cleaner。
另外,考虑使用NullDB来避免访问真实数据库,除非你需要(我的方法是永远不会在单元测试中命中数据库,只在集成测试中)。
答案 5 :(得分:0)