# Testing with transactions

**URL:** <https://www.ruby-forum.com/t/testing-with-transactions/63485>\
**Category:** Rails\
**Created:** [June 15, 2006, 5:17pm UTC](https://www.ruby-forum.com/t/testing-with-transactions/63485 "2006-06-15T17:17:15Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Laas\_Toom](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/59ef9b/32.png) [@Laas\_Toom](https://www.ruby-forum.com/u/Laas_Toom)\
**Post date:** [June 15, 2006, 5:17pm UTC](https://www.ruby-forum.com/t/testing-with-transactions/63485/1 "2006-06-15T17:17:15Z")

</div>

Hello!

I experienced problems with testing transactions which are supposed to  
be  
rolled back, but are not, because of transactional fixtures eliminating  
the  
inner transaction. Can this be worked around somehow without turning off  
transactional fixtures? Maybe savepoints can help this?

Does anyone have any experience with savepoints to achieve nested  
transaction  
functionality? Both Postgres and MySQL support savepoints (didn’t check  
others).

I was thinking to make a custom patch for AR to create savepoints for  
inner  
transactions. Can somebody help me with achieving this (esp. with  
connection\_adapters and wrapping this all up as a plugin perhaps).

Something in the way of:

# Wrap a block in a transaction. Returns result of block.

def transaction(start\_db\_transaction = true)  
transaction\_open = false  
savepoint\_open = false  
savepoint\_name = nil  
begin  
if block\_given?  
if start\_db\_transaction  
begin\_db\_transaction  
transaction\_open = true  
else  
savepoint\_name = create\_savepoint  
savepoint\_open = true  
end  
yield  
end  
rescue Exception =\> database\_transaction\_rollback  
if transaction\_open  
transaction\_open = false  
rollback\_db\_transaction  
end  
if savepoint\_open  
savepoint\_open = false  
rollback\_to\_savepoint(savepoint\_name)  
end  
raise  
end  
ensure  
commit\_db\_transaction if transaction\_open  
release\_savepoint(savepoint\_name) if savepoint\_open  
end

Best regards,  
Laas

---

<div class="post-metadata">

**Author:** ![Laas\_Toom](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/59ef9b/32.png) [@Laas\_Toom](https://www.ruby-forum.com/u/Laas_Toom)\
**Post date:** [June 15, 2006, 7:25pm UTC](https://www.ruby-forum.com/t/testing-with-transactions/63485/2 "2006-06-15T19:25:17Z")

</div>

You can use a database that support nested transactions.

Pg and Oracle both do, I believe.

–  
– Tom M.

---

<div class="post-metadata">

**Author:** ![Laas\_Toom](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/59ef9b/32.png) [@Laas\_Toom](https://www.ruby-forum.com/u/Laas_Toom)\
**Post date:** [June 15, 2006, 9:39pm UTC](https://www.ruby-forum.com/t/testing-with-transactions/63485/3 "2006-06-15T21:39:44Z")

</div>

I do most of my testing with transactional fixtures, but where I need to  
test a transaction itself, I create a separate test module like:

require File.dirname( **FILE** ) + ‘/…/test\_helper’

class MyTestNoTransFixturesTest \< Test::Unit::TestCase  
self.use\_transactional\_fixtures = false  
fixtures :myfixture

def test01\_my\_test  
# tests and assertions  
end  
end

Julian

---

<div class="post-metadata">

**Author:** ![Laas\_Toom](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/59ef9b/32.png) [@Laas\_Toom](https://www.ruby-forum.com/u/Laas_Toom)\
**Post date:** [August 3, 2006, 2:24pm UTC](https://www.ruby-forum.com/t/testing-with-transactions/63485/4 "2006-08-03T14:24:05Z")

</div>

This is very cool. Haven’t tried it yet, but I encourage you to submit  
this as a patch to the core team.

–  
– Tom M.

---

<div class="post-metadata">

**Author:** ![Laas\_Toom](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/59ef9b/32.png) [@Laas\_Toom](https://www.ruby-forum.com/u/Laas_Toom)\
**Post date:** [June 20, 2006, 7:33pm UTC](https://www.ruby-forum.com/t/testing-with-transactions/63485/5 "2006-06-20T19:33:07Z")

</div>

Hello!

Instead of rewriting some of my tests to use non-transactional fixtures,  
I  
thought it would be more wise to patch AR insted. So I ended up writing  
a  
plugin, which now is availlable from:

[http://rubyforge.org/projects/arnesttransacts](http://rubyforge.org/projects/arnesttransacts)

This plugin uses savepoints when one transaction has already been  
started and  
rolls back to/commits that savepoint instead. This is implemented by  
overlaying  
ActiveRecord::ConnectionAdapters::DatabaseStatements.transaction  
method and adding some helper methods to postgres and mysql adapters  
also.

Currently only PostgreSQL is tested, though MySQL is also implemented,  
as it  
uses the same syntax, but I did not have time to test it with live  
database.

It would be great if some Oracle, DB2 or Firebird users could implement  
this  
plugin for their database also.

Comments and thougths are welcome.

Best Regards,  
Laas Toom
