How to run unit tests w/o first blowing away test db?

Fearless Fool wrote: [...]

Marnen, maybe I misunderstand you, but even if I knew a priori which TimeDimension records my tests were going to use,

Uh...what? How can you *not* know a priori how your tests should behave? If you don't know the results you expect a priori, then you can't write proper tests.

It sounds like there's something wrong, or at least strange, with your testing methodology. Can you post some example test code so I can see how you're using these records?

it's a PITA to generate TimeDimension records piecemeal (what day did Easter fall on in 2005?)

Who cares? Just generate a TimeDimension record that has the properties you need for the particular test. If that means saying Easter fell in December, that's perfectly OK.

Furthermore, I have other large constant tables such as the location of FAA certified airports in North America, cobbled from multiple sources. Again, it would be a pain to figure out exactly which ones my test code will reference and then ETL their records on demand.

You shouldn't need to ever do that in your tests. Just create fake data that has the properties you want to test.

Best,

Marnen Laibow-Koser wrote:

[snip] Sent from my iPhone

Wow - that's some agile thumbs you've got there.

Yes, I could create mock classes that fake the data for exactly the items I need. But:

Since I already have the static tables (and have tested them), wouldn't that be analogous to writing a Math::sin(x) function that is defined only for specific values of x?

To extend the analogy, Math::sin(x) is not part of the business logic of my app, and I should not be testing it any more than I should be testing whether or not :belongs_to generates the correct methods in ActiveRecord.

In these circumstances, I'd maintain that I'm MORE likely to introduce errors in my tests by writing mock classes when stable, proven data already exists.

Can't you just be happy that I'm not using fixtures now? :slight_smile:

- ff

Fearless Fool wrote:

Marnen Laibow-Koser wrote:

[snip] Sent from my iPhone

Wow - that's some agile thumbs you've got there.

I take the "agile" part of my job seriously. :smiley:

Yes, I could create mock classes

No one is talking about mock objects, exactly. The objects you'd be creating with factories would be real AR objects, with real DB records behind them. There just wouldn't be 85,000 of them.

Think about it: no test case is going to touch more than about 5 records maximum. You're just not creating the 84,995 you won't use.

that fake the data for exactly the items I need. But:

Since I already have the static tables (and have tested them), wouldn't that be analogous to writing a Math::sin(x) function that is defined only for specific values of x?

Sort of. And that's a good testing practice: Math::sin is already well tested, so you don't need to test it further. So don't incur the overhead of calling it.

Now, for a cheap function like sin, the difference in performance is trivial. For 84,995 unnecessary records, the difference is not trivial.

To extend the analogy, Math::sin(x) is not part of the business logic of my app, and I should not be testing it any more than I should be testing whether or not :belongs_to generates the correct methods in ActiveRecord.

Correct. So don't bother calling it in your tests -- or in the analogy, don't bother testing your already tested gargantuan constant table.

In these circumstances, I'd maintain that I'm MORE likely to introduce errors in my tests by writing mock classes when stable, proven data already exists.

You're not writing mocks. And you'll be *less* likely to introduce errors, because you know that your specially crafted test data has exactly the properties that your tests need it to.

With crafted test data, you're testing your application.

With your whole constant table, you're testing your constant table -- which you say you've already tested -- not your app code, and you're working harder to do it. There's no advantage to this approach, and several disadvantages. Don't do it.

Can't you just be happy that I'm not using fixtures now? :slight_smile:

But you *are* using fixtures. You may not be using the Rails fixtures mechanism, but you're still using brittle, permanent test fixtures instead of the flexible crafted test data you should be using. This is a terrible idea. There is not a single reason to do it that way. Do not do it.

- ff

Best,

insert the following code to your Rakefile

# Monkey patch Rake : Rake::TaskManager.class_eval do   def remove_task(task_name)     @tasks.delete(task_name.to_s)   end end

before the line require 'tasks/rails'

The create a new file test.rake under Libs/tasks :

Rake.application.remove_task 'db:test:prepare' namespace :db do   namespace :test do     task :prepare do |t|       puts "\nData in the test database will not be deleted !!!!\n"     end   end end

Who cares? Just generate a TimeDimension record that has the properties you need for the particular test. If that means saying Easter fell in December, that's perfectly OK.

So your test is running fine when Easter fells in December... and then you are going in production with your application, you will have a lot of fun ;-))

Seriously, I too prefer to have some realistic test data and no artificially created test stubs, which have some assumptions about reality which often fails... phone numbers will always have seven digits and surnames will never include a hyphen and Easter will always be in December....

My 2cts

Klaus

Klaus-dieter Gundermann wrote: [...]

Seriously, I too prefer to have some realistic test data and no artificially created test stubs, which have some assumptions about reality which often fails... phone numbers will always have seven digits and surnames will never include a hyphen and Easter will always be in December....

Then you're doing your test data wrong. The point of crafted test data is that you *can* test what happens with an eight-digit phone number -- even if all your real data has seven-digit numbers. Be imaginative before your users are. And if your users do somehow discover a bug before you do, make a test case out of it.

Klaus-dieter Gundermann wrote: [...]

Seriously, I too prefer to have some realistic test data and no artificially created test stubs, which have some assumptions about reality which often fails... phone numbers will always have seven digits and surnames will never include a hyphen and Easter will always be in December....

Then you're doing your test data wrong. The point of crafted test data is that you *can* test what happens with an eight-digit phone number -- even if all your real data has seven-digit numbers. Be imaginative before your users are. And if your users do somehow discover a bug before you do, make a test case out of it and put it into your future crafted test data.