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.