Setting up a test database on a ruby on rails continuous integration server using SQL instead of schema.rb

For developing our Ruby on Rails based web site, we usually take regular SQL dumps from our production servers (of course, anonymizing sensitive customer data along the way). Always having a fresh dump allows us to be on the safe side when writing database migrations. Having an up to date development database enables us to run our test suite as well; it’s just a matter of rake db:test:prepare to get our test database up-to-date. So far, so good.
Due to our use of some MySQL specific stuff (namely full-text-indices), which are not supported by the database agnostic schema.rb, we’re using config.active_record.schema_format = :sql. This makes rake db:test:prepare use db:test:clone_structure instead of db:test:load. Unfortunately, db:test:clone_structurealways calls db:structure:dump, which tries to dump the development database structure to an SQL file. This is ok on a developer’s box but we ran into trouble on our continuous integration server.

We don’t want to setup a development environment on our CI server (which requires loading an anonymized production dump – quite a beast). It’s enough for us to have a test environment there, using a checked out development_structure.sql (created on a development box and checked into version control) to create the test database. Unfortunately, the rake tasks provided by rails do not cover this scenario.

So, we simply came up with the following addition to rails’ set of rake tasks:

rake db:test:load_structure reads the checked out development_structure.sql and applies it to the test database (which it recreates first by defining db:test:purge as a pre-requisite). That’s all we need to have a fully up-to-date test database on our CI server! No need to worry about creating a full development environment there just to be able to run migrations and dump the updated schema prior to setting up the test database.

This looks great, though I may be making a dumb mistake. I’m running this command, to ensure the db is created before we run tests:

RAILS_ENV=test rake db:test:load_structure test:units –trace

load_structure works great, but then when test:units runs, it calls db:test:clone_structure which dies with mysql errors, because the tables already exist. Am I doing something wrong? Output looks like this:

Blog Updates

The Book

The Chef Infrastructure Automation Cookbook contains practical recipes on everything you will need to automate your infrastructure using Chef. The book is packed with illustrated code examples to automate your server and cloud … Read more...