How to avoid tests removing data that my migrations put in?


#1

hi,

I have an issue in that I have some reference data my migrations run
in. However when running “rake spec” it seems to remove the data in
the test database up front.

What do you recommend to workaround this issue?

Thanks
Greg


#2

On Tue, Nov 4, 2008 at 2:45 PM, Greg H. <
removed_email_address@domain.invalid> wrote:

I have an issue in that I have some reference data my migrations run
in. However when running “rake spec” it seems to remove the data in
the test database up front.

What do you recommend to workaround this issue?

Don’t do that. :slight_smile: At least, that’s my opinion. Depending on database
contents for testing is a brittle road to hoe. As I just finished
saying, I
like my test database to be clean and identical in schema to my
development
database. ‘rake spec’ does that.

Without knowing your situation exactly, I would suggest either mocking
out
calls that you expect to deliver the prepopulated data, creating that
data
in your specs as needed, writing fixtures that load the data in, and/or
examining whether that data is really necessary for testing.

///ark


#3

“Greg H.” removed_email_address@domain.invalid writes:


rspec-users mailing list
removed_email_address@domain.invalid
http://rubyforge.org/mailman/listinfo/rspec-users

You should probably create it in a before block, or if the reference
data is always going to be the same, you’ll want to insert it into the
db BEFORE the test transactions start. That will require a bit of
work…clear out all the tables and insert the data, that way when
transactions get rolled back you’re back at the db with reference data.
I’m not quite sure how to do that though. Is there a before(:suite)
that might work?

Pat


#4

Sent from my iPhone

On 5. nov… 2008, at 00.05, Pat M. removed_email_address@domain.invalid wrote:

Thanks
transactions get rolled back you’re back at the db with reference
data.
I’m not quite sure how to do that though. Is there a before(:suite)
that might work?

There is no need for a special construct. Just do it at the top level
in env.rb or an adjacent file. Use at_exit for a global “teardown”.


#5

Aslak Hellesøy wrote:

I have an issue in that I have some reference data my migrations run
http://rubyforge.org/mailman/listinfo/rspec-users
There is no need for a special construct. Just do it at the top level
in env.rb or an adjacent file. Use at_exit for a global “teardown”.

I believe they are talking about rspec examples and not cucumber
features…
-Ben


#6

Ben M. removed_email_address@domain.invalid writes:

removed_email_address@domain.invalid

There is no need for a special construct. Just do it at the top
level in env.rb or an adjacent file. Use at_exit for a global
“teardown”.

I believe they are talking about rspec examples and not cucumber features…

aslak’s right though in that case too. In your spec_helper, just loop
over the tables and delete everything, then insert the seed data you
want, and it should be good to go.

Pat


#7

On Tue, Nov 4, 2008 at 4:56 PM, Pat M. removed_email_address@domain.invalid wrote:

Then it becomes a simple matter of SeedData.build_data
to kick off the whole deal.

That makes sense.

///ark


#8

On Tue, Nov 4, 2008 at 4:26 PM, Pat M. removed_email_address@domain.invalid wrote:

aslak’s right though in that case too. In your spec_helper, just loop
over the tables and delete everything, then insert the seed data you
want, and it should be good to go.

But then Ashley’s comment applies: you’ve got the same facts in two
places.
Best thing is to avoid the dependency, if at all possible.

///ark


#9

so is the concept to build up all seed data creation in one
place/method, & then for the rake spec case run this in via the “test”
environment.rb file?

But then if you were to use rake:migrate to drop back a couple of
version you might be in a spot of bother? (ie newest seed data not
then tied to migration)?


#10

“Mark W.” removed_email_address@domain.invalid writes:

On Tue, Nov 4, 2008 at 4:26 PM, Pat M. removed_email_address@domain.invalid wrote:

aslak's right though in that case too.  In your spec_helper, just loop
over the tables and delete everything, then insert the seed data you
want, and it should be good to go.

But then Ashley’s comment applies: you’ve got the same facts in two places. Best thing is to
avoid the dependency, if at all possible.

Sure, but you can encapsulate all that stuff too. When I’ve done stuff
like this in the past (and on second thought I have done it just as
aslak suggested, I just didn’t think of it :slight_smile: we’ve created some seed
data builders. Then it becomes a simple matter of SeedData.build_data
to kick off the whole deal.

Pat


#11

I’ll just point out one more disadvantage of assuming the contents of
the
test database are correct (without ‘rake db:test:prepare’). If you
interrupt
a test with Ctrl-C (especially when running autospec), it’s possible for
the
transaction not to get rolled back. An uncommitted transaction should
get
rolled back automatically, but I’ve seen that fail to happen, at least
with
PostgreSQL 8.1. A test would assume that a given table is empty, they’d
add
a row, expect the count to be 1, and it would fail because of existing
cruft. I eventually learned to run ‘rake spec’ when weird failures
happened.
Just something to keep in mind.

///ark


#12

“Greg H.” removed_email_address@domain.invalid writes:

so is the concept to build up all seed data creation in one
place/method, & then for the rake spec case run this in via the “test”
environment.rb file?

That sounds good. I typically put it in spec_helper.rb so all
test-related stuff is in one place, but I think it makes a lot of sense
to treat this as part of the environment.

But then if you were to use rake:migrate to drop back a couple of
version you might be in a spot of bother? (ie newest seed data not
then tied to migration)?

Let me know if I’m understanding your problem correctly…if you put the
seed data in test.rb, then it’ll try to load it regardless of whether it
matches the db schema. Is that right? If that’s the case, I suppose
you could do a check to see if you even need to load seed data.
Basically, if there are already users in the test db, no need to do
anything. This would let you have a fully-migrated db with seed data
that you then migrated down. But honestly I’m not sure why you would
want to drop the schema back down a couple of versions in the first
place?

Pat


#13

“Mark W.” removed_email_address@domain.invalid writes:

I’ll just point out one more disadvantage of assuming the contents of the test database are
correct (without ‘rake db:test:prepare’). If you interrupt a test with Ctrl-C (especially when
running autospec), it’s possible for the transaction not to get rolled back. An uncommitted
transaction should get rolled back automatically, but I’ve seen that fail to happen, at least
with PostgreSQL 8.1. A test would assume that a given table is empty, they’d add a row, expect
the count to be 1, and it would fail because of existing cruft. I eventually learned to run
‘rake spec’ when weird failures happened. Just something to keep in mind.

Well that is fascinating. It seems very, very wrong. Something I might
expect from MySQL, but never postgres… :slight_smile:

Pat


#14

how to I get a model statement to run within “test.rb” by the way?
For example to get the following to run:

  RecurringType.create(:name => "TYPE_BASIC")

If I just stick this in I get:

--------------------extract------------------
Macintosh-2:myequity greg$ rake spec
(in /Users/greg/source/myequity)
/opt/local/lib/ruby/gems/1.8/gems/activerecord-2.1.1/lib/active_record/connection_adapters/abstract/connection_specification.rb:265:in
retrieve_connection': ActiveRecord::ConnectionNotEstablished (ActiveRecord::ConnectionNotEstablished) from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.1.1/lib/active_record/connection_adapters/abstract/connection_specification.rb:78:inconnection’
from
/opt/local/lib/ruby/gems/1.8/gems/activerecord-2.1.1/lib/active_record/base.rb:1149:in
columns' from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.1.1/lib/active_record/base.rb:2616:inattributes_from_column_definition_without_lock’
from
/opt/local/lib/ruby/gems/1.8/gems/activerecord-2.1.1/lib/active_record/locking/optimistic.rb:55:in
attributes_from_column_definition' from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.1.1/lib/active_record/base.rb:2137:ininitialize’
from
/opt/local/lib/ruby/gems/1.8/gems/activerecord-2.1.1/lib/active_record/base.rb:642:in
new' from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.1.1/lib/active_record/base.rb:642:increate’
from
/Users/greg/source/myequity/config/environments/test.rb:24:in
load_environment' ... 14 levels... from /Users/greg/source/myequity/vendor/plugins/rspec/lib/spec/runner/example_group_runner.rb:13:inload_files’
from
/Users/greg/source/myequity/vendor/plugins/rspec/lib/spec/runner/options.rb:98:in
run_examples' from /Users/greg/source/myequity/vendor/plugins/rspec/lib/spec/runner/command_line.rb:19:inrun’
from /Users/greg/source/myequity/vendor/plugins/rspec/bin/spec:4
rake aborted!
Command /opt/local/bin/ruby
-I"/Users/greg/source/myequity/vendor/plugins/rspec/lib"
“/Users/greg/source/myequity/vendor/plugins/rspec/bin/spec”
“spec/lib/hash_extensions_spec.rb” “spec/models/bank_account_spec.rb”
“spec/models/frequency_spec.rb” “spec/models/interest_rate_spec.rb”
“spec/models/projections/projections_spec.rb”
“spec/models/recurring_spec.rb” “spec/models/recurring_type_spec.rb”
“spec/models/transaction_spec.rb” --options
“/Users/greg/source/myequity/spec/spec.opts” failed


#15

Oh, I guess it makes sense that it wouldn’t work there. The stuff in
test.rb is run as part of the initializer block, meaning that Rails
hasn’t been set up yet there. I would just stick it all in
spec_helper.rb. That’s what I do and was my initial instinct, because
it keeps all the test setup in one place. And it looks like it’s by far
the easiest way, too :slight_smile:

Pat

“Greg H.” removed_email_address@domain.invalid writes: