public
Last active

RSpec is not the reason your rails test suite is slow

  • Download Gist
output.txt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
[david: compare]$ # at this point we have a stock rails app with no minitest tests and one pending rspec example
[david: compare]$
[david: compare]$ time rake test
Run options:
 
# Running tests:
 
 
 
Finished tests in 0.030419s, 0.0000 tests/s, 0.0000 assertions/s.
 
0 tests, 0 assertions, 0 failures, 0 errors, 0 skips
 
real 0m5.694s
user 0m4.503s
sys 0m0.811s
[david: compare]$ time rake spec
/Users/david/.rvm/rubies/ruby-1.9.3-p0/bin/ruby -S rspec ./spec/models/thing_spec.rb
*
 
Pending:
Thing add some examples to (or delete) /Users/david/tmp/compare/spec/models/thing_spec.rb
# No reason given
# ./spec/models/thing_spec.rb:4
 
Finished in 0.00072 seconds
1 example, 0 failures, 1 pending
 
real 0m4.918s
user 0m3.839s
sys 0m0.697s
[david: compare]$
[david: compare]$ echo 'require "test_helper"
>
> class ThingTest < ActiveSupport::TestCase
> test "empty" do
> end
> end
> ' > test/unit/thing_test.rb
[david: compare]$
[david: compare]$ echo 'require "spec_helper"
>
> describe Thing do
> example "empty" do
> end
> end
> ' > spec/models/thing_spec.rb
[david: compare]$
[david: compare]$ time rake test
Run options:
 
# Running tests:
 
.
 
Finished tests in 0.078296s, 12.7720 tests/s, 0.0000 assertions/s.
 
1 tests, 0 assertions, 0 failures, 0 errors, 0 skips
 
real 0m5.802s
user 0m4.565s
sys 0m0.847s
[david: compare]$ time rake spec
/Users/david/.rvm/rubies/ruby-1.9.3-p0/bin/ruby -S rspec ./spec/models/thing_spec.rb
.
 
Finished in 0.00475 seconds
1 example, 0 failures
 
real 0m4.950s
user 0m3.903s
sys 0m0.725s
[david: compare]$
[david: compare]$ echo 'require "test_helper"
>
> class ThingTest < ActiveSupport::TestCase
> 1000.times.map do |n|
> test "empty #{n}" do
> end
> end
> end
> ' > test/unit/thing_test.rb
[david: compare]$
[david: compare]$ echo 'require "spec_helper"
>
> describe Thing do
> 1000.times.map do |n|
> example "empty #{n}" do
> end
> end
> end
> ' > spec/models/thing_spec.rb
[david: compare]$
[david: compare]$ time rake test
Run options:
 
# Running tests:
 
........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
 
Finished tests in 0.753860s, 1326.5062 tests/s, 0.0000 assertions/s.
 
1000 tests, 0 assertions, 0 failures, 0 errors, 0 skips
 
real 0m6.730s
user 0m5.047s
sys 0m0.887s
[david: compare]$ time rake spec
/Users/david/.rvm/rubies/ruby-1.9.3-p0/bin/ruby -S rspec ./spec/models/thing_spec.rb
........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
 
Finished in 0.99978 seconds
1000 examples, 0 failures
 
real 0m6.023s
user 0m4.615s
sys 0m0.790s
script.sh
Shell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
rails new compare
cd compare
rails g model thing name:string
echo "gem 'rspec-rails', '2.9.0.rc2', :group => [:development, :test]" >> Gemfile
bundle
rails g rspec:install
rails g model thing name:string --skip-migration
rake db:migrate
rake db:test:prepare
 
# at this point we have a stock rails app with no minitest tests and one pending rspec example
 
time rake test
time rake spec
 
echo 'require "test_helper"
 
class ThingTest < ActiveSupport::TestCase
test "empty" do
end
end
' > test/unit/thing_test.rb
 
echo 'require "spec_helper"
 
describe Thing do
example "empty" do
end
end
' > spec/models/thing_spec.rb
 
time rake test
time rake spec
 
echo 'require "test_helper"
 
class ThingTest < ActiveSupport::TestCase
1000.times.map do |n|
test "empty #{n}" do
end
end
end
' > test/unit/thing_test.rb
 
echo 'require "spec_helper"
 
describe Thing do
1000.times.map do |n|
example "empty #{n}" do
end
end
end
' > spec/models/thing_spec.rb
 
time rake test
time rake spec

Of course RSpec isn't the speed problem. Enough of us know that the speed problems come from loading unnecessary dependencies for the majority of your code, such as rails. Once people start designing their systems with this in mind, this becomes very clear.

@coreyhaines There are some skeptics that believe that RSpec is bloated and adds nothing valuable to a test suite. Apparently, these people think that unless something is difficult, it can't be efficient. :-)

@jgaskins
I have talked to people with that opinion. They are free to have their opinions. In the end, though, there are many options people can choose. That's a beautiful thing. :)

@coreyhaines I agree it's definitely is nice to have the choice, but I wouldn't call believing RSpec to be a testing bottleneck to be an opinion — rather, I see it as FUD, usually caused by not knowing what's going on when they run bundle exec and/or require spec_helper.rb in their specs.

@jgaskins
I try to stay away from getting into their reasons and saying they don't understand things. Whether it is true, or not, it just ends up leading to purse fights. :)
For the record, I neither use bundle exec to run my specs nor require spec_helper in most of my specs. :)

@coreyhaines lol You're very right. Unfortunately, my desire not to start flame wars on the internet is all too often at odds with my tendency to "someone is wrong on the internet!" :-)

@jgaskins :) Yeah, staying out of it is a lot easier said than done. I contribute my fair share of purse fighting when people are wrong on the internet. :)

I'll bite :)

I don't think rspec itself is slow, but I do get the impression that rspec lends itself to writing slow tests via overly isolated assertions with before blocks. Granted, there are advantages to isolated assertions, deep nesting can lead to longer-than-necessary test setup. SCSS often suffers the same fate.

'speed problems come from loading unnecessary dependencies for the majority of your code, such as rails'

@coreyhaines or anyone else, any links/advice on how to reduce those rails dependencies?

I still need to read it, but I understand http://objectsonrails.com/
has good thoughts on the topic of keeping Rails dependencies at bay.
At least according to
http://rubyrogues.com/046-rr-objects-in-rails-part-2/

@gavingmiller http://objectsonrails.com/ shows an approach of developing a rails app with tests that load only what's strictly necessary to run the tests. I haven't tried this approach yet but sounds interesting.

This is the way I develop my applications, and it is wonderful.
On Mar 22, 2012 2:01 PM, "Emmanuel Oga" <
reply@reply.github.com>
wrote:

@gavingmiller http://objectsonrails.com/ shows an approach of developing
a rails app with tests that load only what's strictly necessary to run the
tests. I haven't tried this approach yet but sounds interesting.


Reply to this email directly or view it on GitHub:
https://gist.github.com/2050539

Gary Bernhardt does a great job of showing how to reduce test dependencies at https://www.destroyallsoftware.com

+1 to both DAS and Objects On Rails. Those were my sources of techniques to speed up my test suite.

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.