I am running mysql, database_cleaner, Rspec, etc. I have about 518 tests so far and they take 88 seconds to run. This is unacceptable to me as my app development is just beginning.
So before going further, I'd like to try and find ways to reduce the time it takes to run these tests - hopefully without having to actually change the tests.
In most cases, I am trying to use stubs. However, when I am testing models and queries, I do use the database.
I think database_cleaner is slowing them down, but I don't know how to test queries and stuff without it.
Using sqlite3 with the ":memory:" option only seems to shave off about 10 seconds (kind of disappointing result...)
What can I do to really speed up my tests?
We can run all of our tests at once by using the bin/rails test command. Or we can run a single test file by passing the bin/rails test command the filename containing the test cases. This will run all test methods from the test case.
To run a Minitest test, the only setup you really need is to require the autorun file at the beginning of a test file: require 'minitest/autorun' . This is good if you'd like to keep the code small. A better way to get started with Minitest is to have Bundler create a template project for you.
What is Minitest? Minitest is a testing tool for Ruby that provides a complete suite of testing facilities. It also supports behaviour-driven development, mocking and benchmarking.
While unit tests make sure that individual parts of your application work, integration tests are used to test that different parts of your application work together.
There's a variety of strategies you can use to speed up your test times. If you're just starting, and you're seeing an 88 second run time, I would imagine a good number of these apply to you:
Ryan Brunner offered a lot of great advice. Everything he said is true in general, yet did not apply to me.
I didn't mention Factory Girl because I didn't think to mention it (don't ask). It turned out to be very relevant detail because it was responsible for the tests running so slow.
By simply removing Factory girl completely from my controller tests (I was using Factory.build
), I have managed to get them down from 50 seconds to something like 5.
The reason is that Factory.build
calls Factory.create
for associations, which causes a database hit... so if you have a lot of associations, it will take awhile to create a new model object. But even more, that only accounted for 30-35% of the overhead in my case. Factory_girl was actually spending 65-70% of its time doing non-database stuff. I have no idea why, but after forcing every call to be Factory.build
, it will still taking quite awhile to build my objects. Going with basic MyClass.new
ended up being MUCH faster.
My entire test suite now takes a little under 30 seconds instead of up to 90 seconds. That is a 300% speed increase in general by making these changes... but when it came to the controller tests, I got a 2000% speed increase - and I was already stubbing! All of that performance overhead was due to Factory.build
! That is where most of the gains came from.
Of course, I went back into my models and used Factory.build
or simply MyClass.new
wherever I could.
I also added :default_strategy => :build
in factories.rb
too whenever I could, to prevent Factory Girl from hitting the database. If you ask me, this should be the default as only 1 test failed as a result of this change, but I managed to get 10 entire seconds out of my model tests by this change alone.
If you're having problems like I am, follow these steps and you should notice a 2-3x speed improvement with not much drawback.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With