Ruby-on-rails – How to prepare test database(s) for Rails rspec tests without running rake spec

rspecrspec2ruby-on-railsruby-on-rails-3specjour

After significant troubleshooting, I figured out that I needed to run rake spec once (I can abort with control-c) before I can run rspec directly (e.g. on a subset of our specs). We are running Rails 3.0.7 and RSpec 2.5.0.

Clearly, rake is running some important database setup tasks / code (we have custom code in the root level rails Rakefile and possibly other places).

How can I run the rake test database setup tasks / code without running rake spec?

In addition to being able to run rspec on a subset of files, I am using specjour to spread our specs across multiple cores (haven't had success with spreading them across the LAN yet), but I see the same behavior as for running rspec directly: I need to run rake spec on each test database (assuming two cores) before specjour works:

rake spec TEST_ENV_NUMBER=1
control-c (after tests start)
rake spec TEST_ENV_NUMBER=2
control-c (after tests start)
specjour

Note: my config/database.yml has this entry for test (as is common for the parallel testing gems):

test:
  adapter: postgresql
  encoding: unicode
  database: test<%=ENV['TEST_ENV_NUMBER']%>
  username: user
  password:

parallel_tests seems to set up its databases correctly, but many of our specs fail.

I should also mention that running specjour prepare causes Postgres to log errors that it can't find the databases, but it creates them (without tables). On a subsequent run, no errors are logged, but also no tables are created. It is possible that my whole issue is simply a bug in prepare, so I reported it on github.

I think that I can run arbitrary code on each specjour test database by setting Specjour::Configuration.prepare in .specjour/hooks.rb, so if there's any rake tasks or other code that I need to run, it may work there.

Best Answer

I would recommend dropping your test database, then re-create it and migrate:

bundle exec rake db:drop RAILS_ENV=test
bundle exec rake db:create RAILS_ENV=test
bundle exec rake db:schema:load RAILS_ENV=test

After these steps you can run your specs:

bundle exec rspec spec

gerry3 noted that:

A simpler solution is to just run rake db:test:prepare

However, if you're using PostgreSQL this wont work because the rails environment gets loaded, which opens a database connection. This causes the prepare call to fail, because the DB cannot be dropped. Tricky thing.