37

I started making a Rails 3.1 engine, and I'm having a hard time testing it using rspec.

First of all, if I run rails g integration_test whatever it creates a regular integration test in tests/integration instead of spec/requests (the rspec-rails gem is installed and required as a development dependency in the gemspec file)

Also, when I run a spec test I get an error saying the table corresponding to the model I'm testing has not been created. I tried rake engine_name:install:migrations and running rake db:migrate from inside the dummy app, and I get a "table already exists" error.

Everything just seems disconnected, I feel I'm missing something here to make the rspec gem work seamlessly as it usually does with full rails applications.

I followed all the changes from here http://rubyx.com/2011/03/01/start-your-engines and I can test the engine manually by launching the dummy app via the console as shown here http://railscasts.com/episodes/277-mountable-engines.

Is there a way to make rspec the default for testing a rails 3.1 engine?

deb
  • 12,326
  • 21
  • 67
  • 86
  • In rails 3.2 some of this has been resolved, but I always forget how to migrate the test database. To run migrations on the test database, run `rake app:db:test:prepare` in your gem's directory. – Andrew Mar 21 '13 at 05:25
  • I just implemented the method in this article with no problems. http://viget.com/extend/rails-engine-testing-with-rspec-capybara-and-factorygirl – jspooner Sep 16 '13 at 18:18

2 Answers2

62

I am using RSpec with a Rails engine without issues.

I created my plugin using the following switches: -T --full --dummy-path=spec/dummy.

  • -T excludes test/unit
  • --full indicates that the plugin is an engine
  • --dummy-path is simply so that we don't get a test directory (the default is test/dummy).

From there I used the spec_helper from the "start your engines" article:

# Configure Rails Envinronment
ENV["RAILS_ENV"] = "test"
require File.expand_path("../dummy/config/environment.rb",  __FILE__)

require 'rspec/rails'

ENGINE_RAILS_ROOT=File.join(File.dirname(__FILE__), '../')

# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[File.join(ENGINE_RAILS_ROOT, "spec/support/**/*.rb")].each {|f| require f }

RSpec.configure do |config|
  config.use_transactional_fixtures = true
end

For the generators. I add a config.generators block to my engine.rb file like so:

module MyEngine
  class Engine < Rails::Engine
    config.generators do |g|
      g.test_framework :rspec, :view_specs => false
    end
  end
end

With that, I'm able to get rspec tests when running a generator like the model generator.

As for the DB, is your database.yml file set up correctly? Did you load the test environment, e.g. rake db:test:clone or rake db:migrate RAILS_ENV=test? My guess is that RSpec can't see your tables because there isn't a test database set up.

dwhite
  • 1,979
  • 1
  • 24
  • 43
  • 1
    shouldn't I use `--mountable` instead of `--full`? – deb Sep 21 '11 at 01:02
  • I followed the changes in your answer but I still can't use the generator. if I try `rails g integration_test posts` nothing happens. Maybe you left something out? – deb Sep 21 '11 at 01:40
  • I don't use the integration_test generator so I'm not sure. Just passing --full means that it is a standard engine non-namespaced and will generate the dummy project. I'm pretty sure you need to pass --full for a --mountable as well in order to get the dummy project to generate, but maybe that changed since the RC? What happens if you do a rails g model... or a controller? – dwhite Sep 21 '11 at 02:14
  • I removed `g.test_framework :rspec` from the `engine.rb` file and now the integration_generator works. I have no idea why :) Now rails g model is also giving me rspec tests. I think what made the difference was passing `--full` when creating the plugin – deb Sep 21 '11 at 02:26
  • Great to hear! I'm a little surprised why the config.generate didn't work, that's how I was able to customize what was built. So you used -T --full --mountable --dummy-path=spec/dummy? If you want everything to be namespaced and separate from the app, then you need the --mountable switch, otherwise you can just pass --full on its own. Did you solve your test DB issues as well? – dwhite Sep 21 '11 at 02:43
  • Ok, what I got so far is if I pass both switches, both --mountable and --full, I need to add g.test_framework :rspec to engine.rb. If I use only --full I don't need that line. If I use only --mountable, the generators won't pick up rspec at all, with or without the config in engine.rb – deb Sep 21 '11 at 03:03
  • I'm still working on the db. I'll update tomorrow. Thank you for your help, I marked your answer as correct. Cheers! – deb Sep 21 '11 at 03:07
  • If you use --mountable alone, you don't get the dummy project, do you? That would be why RSpec isn't generating anything, because there's nothing to generate it against :) – dwhite Sep 21 '11 at 03:07
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/3645/discussion-between-dwhite-and-deb) – dwhite Sep 21 '11 at 03:07
  • You need to add g.integration_tool :rspec in engine.rb for integration tests to use rspec – Aj Gu Feb 07 '12 at 05:58
  • According to the Rails Guides you can use both, --full --mountable. The -T and --dummy-path is what I needed! Thanx for this. You saved me a lot of hacks :P – Theo Scholiadis Jun 08 '12 at 14:15
  • 3
    @dwite You might want to edit your answer to include the fact that the generated specs will need to be blocked with a "module MyEngine ... end", or otherwise you get an "uninitialized contstant" error. – Theo Scholiadis Jun 08 '12 at 14:25
  • Line 2 of engine.rb should read Rails::Engine, not Rail::Engine. – Andrés Bonilla Oct 01 '12 at 04:04
  • 1
    You can use `MyEngine.root` instead of `ENGINE_RAILS_ROOT` – Kris Jun 19 '13 at 15:23
9

I was looking for the same answer and I found the combustion gem* which promise to setup a full environment for spec'ing your engine in a simpler way. Just add

gem.add_development_dependency 'combustion', '~> 0.3.1'

to your gemspec and run

bundle exec combust

to reproduce a full rails app in your spec directory.

*I haven't tried it yet...

Fabio
  • 18,856
  • 9
  • 82
  • 114