How to add RSpec to an existing Rails engine Aug 13 2018 Latest Update: Nov 26 2021
Update 2018-08-27
I ran into a problem with Rails, it couldn't find a database.yml
, this was not because of a Rails missconfiguration but because of the binstub for rails had:
1
APP_PATH = File.expand_path('../../test/dummy/config/application', __FILE__)
And well we change it to use rspec, so it should be:
1
APP_PATH = File.expand_path('../../spec/dummy/config/application', __FILE__)
Table of Contents
- Adding RSpec to an existing Rails engine
- Create a temporary engine to build the dummy app
- Add the dependencies to the gemspec
- Tell the engine where to find the test files
- Update the Rakefile to run the RSpec tests
- Create rails_helper.rb and spec_helper.rb to load tests and libraries
- Add configuration for the Engine generators
Adding RSpec to an existing Rails engine
If we already have a Rails engine and we wish to add RSpec to it, how would we go about it? The solution is not as straightforward as we might think, there are a few details always missing from tutorials or the guides, so I'll try to share what I found and hopefully help someone that has the same issue.
Because we are testing an engine, we will need a testing environment that includes our engine so we can test it. When we build a new engine, Rails generates a dummy application that will serve as the environment to mount the engine and run the tests. And there is where we'll start.
Create a temporary engine to build the dummy app
Generate a new engine with the same name as your engine, skip UnitTest but build the dummy app, this dummy app is the one we will move to the current engine and use as our test environment.
1
rails plugin new same_engine_name --full --dummy-path=spec/dummy -T
The T
flag tells rails to skip the UnitTest. Then copy the spec/ directory to your current engine's root path:
1
cp -r spec PATH_TO/OUR_ENGINE/
Add the dependencies to the gemspec
Engine dependencies are added to the our_engine.gemspec
file:
1
s.add_development_dependency 'rspec-rails'
If we were to use capybara and factory bot, add them but let's just keep it simple for now.
Tell the engine where to find the test files
N.B: As mentioned by the following StackOverflow question/answer, the test_files
configuration might be deprecated/disencouraged (Thanks for pointing this out Steve). I'll leave this section available for archival purposes.
StackOverflow - What is the purpose of test_files
configuration in a gemspec
inside the gemspec file:
1
s.test_files = Dir["spec/**/*"]
If you are replacing Unit/MiniTest with RSpec you can remove all that configuration, unless for some reason you wish to have the two frameworks.
Let's say we will remove the old configuration:
1
2
# we can delete this line if we are no longer going to use it
s.test_files = Dir["test/**/*"]
Update the Rakefile to run the RSpec tests
Update our Rakefile in the engine to be aware of our RSpec tests and let's set our RSpec tests as the default task to run when we just run rake
without arguments.
Rspec task configuration
1
2
3
4
5
6
7
8
require 'rspec/core'
require 'rspec/core/rake_task'
desc "Run all specs in spec directory (excluding plugin specs)"
RSpec::Core::RakeTask.new(:spec => 'app:db:test:prepare')
task :default => :spec
Again removed the code for the previous testing framework if we are replacing it with RSpec.
1
2
3
4
5
6
7
8
9
10
11
# UnitTest configuration - remove if no longer in use
require 'rake/testtask'
Rake::TestTask.new(:test) do |t|
t.libs << 'lib'
t.libs << 'test'
t.pattern = 'test/**/*_test.rb'
t.verbose = false
end
task :default => :test
Create rails_helper.rb and spec_helper.rb to load tests and libraries
Inside the spec
directory, create the file spec_helper.rb
to set up all the RSpec configurations we will use. The following is a basic configuration example add the configurations you would normally use.
1
2
3
4
5
6
7
8
9
#spec_helper.rb
require 'rspec/autorun'
Rails.backtrace_cleaner.remove_silencers!
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
RSpec.configure do |config|
config.mock_with :rspec
config.order = "random"
end
Now let's create rails_helper.rb
, this file will require our spec_helper.rb
and contain all the configuration necessary for rails to know where to load our dummy app and configure RSpec rails preferences.
1
2
3
4
5
6
#rails_helper.rb
require 'spec_helper'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../dummy/config/environment.rb', __FILE__)
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'rspec/rails'
Add configuration for the Engine generators
When we generate a new model, resource, etc. we would like Rails to generate the RSpec test files automatically.
1
2
3
4
5
6
7
8
9
module YourEngineName
class Engine < ::Rails::Engine
config.generators do |g|
g.test_framework :rspec
g.assets false
g.helper false
end
end
end
Now we have our configuration done, we can create tests inside our spec directory and run them from the root of our engine, for example, if we have a User model and we would like to test it, we could create a file inside our spec directory:
1
our_engine/spec/models/users_spec.rb
Write a general test:
1
2
3
4
5
6
7
8
require 'spec_helper'
RSpec.describe User, type: :model do
it "Is a valid user" do
user = User.create(name: "Don")
expect(user.valid?).to eq(true)
end
end
We can now run rake
from the root of our engine and start exploring TDD.
Hope this helps, let me know what you think. If I missed something, let me know and I'll add it.