Organizing rspec 2 tests into 'unit' and 'integration' categories in rails
Asked Answered
W

5

13

How to organize rspec 2 tests into 'unit' (fast) and 'integration' (slow) categories?

  • I want to be able to run all unit tests with just rspec command, but not the 'integration' tests.
  • I want to be able to run only 'integration' tests.
Waggon answered 5/4, 2012 at 13:10 Comment(0)
H
22

We have groups of the same nature. We run then one by one both on the local dev boxes and on the CI.

you can simply do

bundle exec rake spec:unit
bundle exec rake spec:integration
bundle exec rake spec:api

This is what our spec.rake looks like

  namespace :spec do
    RSpec::Core::RakeTask.new(:unit) do |t|
      t.pattern = Dir['spec/*/**/*_spec.rb'].reject{ |f| f['/api/v1'] || f['/integration'] }
    end

    RSpec::Core::RakeTask.new(:api) do |t|
      t.pattern = "spec/*/{api/v1}*/**/*_spec.rb"
    end

    RSpec::Core::RakeTask.new(:integration) do |t|
      t.pattern = "spec/integration/**/*_spec.rb"
    end
  end
Headwaters answered 5/4, 2012 at 13:26 Comment(6)
That's great! but.. I added the file to my lib/tasks, but getting errors: rake aborted! uninitialized constant RspecEstoppel
That's odd, if you have Rspec you should have that simply working for you.Headwaters
I had to add rspec-core to Gemfile and add require 'rspec/core/rake_task' to the file. Strange as I thought having rspec-rails would include those dependencies.Estoppel
There is a typo, at least with my setup it should be "RSpec::Core::RakeTask", not "Rspec::..."Omphale
To be explicit, the file should live at lib/tasks/spec.rakeRobustious
It is recommended by Rspec that you wrap the load rspec/core/rake_task line in a begin/rescue block to catch a LoadError. This will allow your rake tasks to be loaded in environments where Rspec is not available relishapp.com/rspec/rspec-core/docs/command-line/rake-taskRobustious
I
9

One way to do it is to tag your RSpec test cases like this:

it "should do some integration test", :integration => true do
  # something
end

When you execute your test cases use this:

rspec . --tag integration

This will execute all the test cases with the tag :integration => true. For more refer to this page.

Indic answered 5/4, 2012 at 13:18 Comment(3)
Thank you. And is there a way to exclude these 'integration' cases when running rspec command without arguments?Waggon
rspec . --tag ~integration. If you are using zsh then it is a slightly different: rspec . --tag "~integeration"Indic
@Evgenii: You can also put --tag "~integration" in your project .rpsec file. This is my preferred approach. Of course it is overridden by options you might specify explicitly on the command-line, so you still have complete flexibility.Pyromorphite
Y
1

I had to configure my unit and feature tests as follows:

require 'rspec/rails'

namespace :spec do
  RSpec::Core::RakeTask.new(:unit) do |t|
    t.pattern = Dir['spec/*/**/*_spec.rb'].reject{ |f| f['/features'] }
  end

  RSpec::Core::RakeTask.new(:feature) do |t|
    t.pattern = "spec/features/**/*_spec.rb"
  end
end

Had to add require 'rspec/rails' and change Rspec to RSpec in the answer given by @KensoDev.

Yasukoyataghan answered 22/2, 2014 at 19:59 Comment(1)
Why not store your unit tests in a separate directory (e.g. spec/unit), and use a less-complicated pattern (e.g. spec/unit/**/*_spec.rb)?Ministerial
S
0

Notice at https://github.com/rspec/rspec-rails, they are telling you to place the gem under "group :development, :test" like so,

group :development, :test do
  gem 'rspec-rails', '~> 2.0'
end

but if you place this only under :test group only,

group :test do
  gem 'rspec-rails', '~> 2.0'
end

then you'll get the above error.

HTH

Scantling answered 11/9, 2013 at 15:10 Comment(0)
U
0

I suggest to use .rspec file to configure patterns instead of using rake because it's tricky to pass flags to RSpec when using rake.

You can read environment variables in your .rspec file:

<%= if ENV['TEST'] == 'integration' %>
--pattern spec/integration/**/*_spec.rb
<% else %>
<% ENV['TEST'] = 'unit' %>
--pattern spec/unit/**/*_spec.rb
<% end %>

Then you can run TEST=integration rspec to run integration tests or just rspec to run unit tests. The advantage of this approach is that you can still pass flags to it like:

TEST=integration rspec -t login -f doc

Ulrick answered 18/3, 2018 at 3:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.