preloading data before running tests?

Okay - I'm stumped: is there a way to run unit tests without blowing
away data preloaded into the test database?

Details: our system uses a TimeDimension table -- think of it as a
datetime that's been highly decorated with additional info, such as
whether or not it's a holiday and other dimensional database goodness.
Many of our unit tests depend on the presence of the TimeDimension
table, but with ~21K rows it's too expensive to recompute before every
test.

I *thought* that seeds.rb could be used to pre-populate the db before
running unit tests, but I traced through "rake test:units" and it
appears to blow away existing data before running the tests.

For example, the following does NOT work:

  bash$ export RAILS_ENV=test # work with test db
  bash$ rake db:reset # drop, recreate, seed test db
  bash$ rake test:units # blows away the seeds before running (ugh)

So: Is there a way to load persistent data into tables that won't get
nuked running unit tests? (To make it perfectly clear: rollbacks after
each test are fine, its just the initial clearing of the database that I
want to avoid.)

Ideas? Am I missing some obvious rake command or option?

- ff

btw:

bash$ rails --version ; rake --version ; ruby --version
Rails 2.3.8
rake, version 0.8.7
ruby 1.9.1p376 (2009-12-07 revision 26041) [powerpc-darwin9.8.0]

Fearless Fool wrote:

Okay - I'm stumped: is there a way to run unit tests without blowing
away data preloaded into the test database?

Details: our system uses a TimeDimension table -- think of it as a
datetime that's been highly decorated with additional info, such as
whether or not it's a holiday and other dimensional database goodness.
Many of our unit tests depend on the presence of the TimeDimension
table, but with ~21K rows it's too expensive to recompute before every
test.

I *thought* that seeds.rb could be used to pre-populate the db before
running unit tests, but I traced through "rake test:units" and it
appears to blow away existing data before running the tests.

For example, the following does NOT work:

  bash$ export RAILS_ENV=test # work with test db
  bash$ rake db:reset # drop, recreate, seed test db
  bash$ rake test:units # blows away the seeds before running (ugh)

Yes, that's expected and proper behavior. Unit tests that depend on
pre-existing conditions/data are fragile. They are called "Unit Tests"
because they are intended to create isolated examples that are not
subject to any pre-existing conditions, such as pre-existing data. Unit
tests should set up all conditions needed to satisfy the examples
defined in the current test, and then "tear down" said conditions before
executing subsequent tests.

So: Is there a way to load persistent data into tables that won't get
nuked running unit tests? (To make it perfectly clear: rollbacks after
each test are fine, its just the initial clearing of the database that I
want to avoid.)

Not unless you hack your test environment to do, but you do this at your
own risk. By doing so you are violating a core principal of Unit
Testing.

Ideas? Am I missing some obvious rake command or option?

My recommendation is to study up on proper testing techniques. You say
you have 20K+ rows in one of your production/development tables. Are you
going to create 20K+ tests to provide examples for every one of those
pre-conditions? If not they you don't need 20K+ rows in your test
database table. You probably only need two or three good examples of
that data to satisfy the examples you'll be writing.

Besides that, if the data you mentioned is only needed to satisfy a
dependency for test not directly related to that data, then you can
provide your unit tests with objects from a testing data factory such as
Machinist or Factory Girl.

http://github.com/notahat/machinist
http://github.com/thoughtbot/factory_girl