Verifying some understanding about manipulating DB data in before/after callbacks in RSpec


#1

We had an after(:each) callback that looked like this:

PurchaseOrder.find(:all).each {|po|
DraftInvoice.find_all_by_po_number(po.po_number).each {|di| di.destroy}}

which we were hoping would reset some purchase order data in a certain
way.

However, because we have “self.use_transactional_fixtures = true” set in
test_helper.rb, this code was never getting committed.

So, I just want to verify:

Attempting to manipulate data directly in the DB in a before/after
callback doesn’t make sense since those changes will not persist across
tests because of the transactionality implied by
“self.use_transactional_fixtures = true”. Is that correct?

Thanks,
Wes


#2

On Thu, Nov 6, 2008 at 4:32 PM, Wes G. removed_email_address@domain.invalid wrote:

Attempting to manipulate data directly in the DB in a before/after callback
doesn’t make sense since those changes will not persist across tests because
of the transactionality implied by “self.use_transactional_fixtures = true”.
Is that correct?

That’s correct. The philosophy of unit testing is that each test
should be independent, without any reliance on the tests run before or
after it. Each test with the same setup and teardown should begin
with the database and environment in exactly the same state. This is
important to RSpec because you can’t guarantee the order in which
tests or spec files might run. So if you’re relying on state changes,
they won’t necessarily work the way you want them to.

Anyway, what the heck are you writing where it’s important that data
be reset “in a certain way?” If that’s crucial to your code, don’t
test it by relying on after(:each) – just write an example where you
destroy things in whatever order and then verify the results. I might
also suggest, however, that you consider whether it’s really a good
idea to have it crucial to your code.


Have Fun,
Steve E. (removed_email_address@domain.invalid)
ESCAPE POD - The Science Fiction Podcast Magazine
http://www.escapepod.org


#3

Stephen E. wrote:

On Thu, Nov 6, 2008 at 4:32 PM, Wes G. removed_email_address@domain.invalid wrote:

Attempting to manipulate data directly in the DB in a before/after callback
doesn’t make sense since those changes will not persist across tests because
of the transactionality implied by “self.use_transactional_fixtures = true”.
Is that correct?

Anyway, what the heck are you writing where it’s important that data
be reset “in a certain way?”
Fair enough. No, I was just forgetting that the tests are supposed to
be implicitly independent of each other.

What happened here is that WATIR doesn’t conform to this Test::Unit
“rollback” contract, so we were committing changes in one test
that were then breaking other tests later. Our attempt to remedy this
mistake via a misbegotten after(:each) failed because of the
transactional
fixtures.

We’ve since torn down that data via WATIR in the original test itself.

Wes


#4

On Thu, Nov 6, 2008 at 1:32 PM, Wes G. removed_email_address@domain.invalid wrote:

We had an after(:each) callback that looked like this:

PurchaseOrder.find(:all).each {|po|
DraftInvoice.find_all_by_po_number(po.po_number).each {|di| di.destroy}}

which we were hoping would reset some purchase order data in a certain way.

If you’re running ‘rake spec’ then your test database will be completely
empty at the end, except for fixture data.

///ark