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

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Wes G. (Guest)
on 2008-11-06 23:48
(Received via mailing list)
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
Stephen E. (Guest)
on 2008-11-07 00:14
(Received via mailing list)
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
Mark W. (Guest)
on 2008-11-07 00:31
(Received via mailing list)
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
Wes G. (Guest)
on 2008-11-07 00:38
(Received via mailing list)
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
This topic is locked and can not be replied to.