OT: in-memory for testing in Rails

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

OT: in-memory for testing in Rails

Xavier Noria
I asked this in a couple of Rails places without luck. I guess this  
is actually related to Rails, just ask it here in case someone knows  
about it.

The file config/database.yml rails generates has as SQLite database  
for testing ":memory:", but the simplest of the tests in the Agile  
book does not work, it produces this trace:

% ruby test/unit/product_test.rb
Loaded suite test/unit/product_test
Started
E/usr/local/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.1.0/lib/sqlite3/
errors.rb:94:in `check': cannot rollback - no transaction is active  
(SQLite3::SQLException)
         from /usr/local/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.1.0/
lib/sqlite3/resultset.rb:76:in `check'
         from /usr/local/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.1.0/
lib/sqlite3/resultset.rb:68:in `commence'
         from /usr/local/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.1.0/
lib/sqlite3/resultset.rb:61:in `initialize'
         from /usr/local/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.1.0/
lib/sqlite3/statement.rb:158:in `execute'
         from /usr/local/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.1.0/
lib/sqlite3/database.rb:211:in `execute'
         from /usr/local/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.1.0/
lib/sqlite3/database.rb:186:in `prepare'
         from /usr/local/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.1.0/
lib/sqlite3/database.rb:210:in `execute'
         from /usr/local/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.1.0/
lib/sqlite3/database.rb:620:in `rollback'
          ... 11 levels...
         from /usr/local/lib/ruby/1.8/test/unit/autorunner.rb:200:in  
`run'
         from /usr/local/lib/ruby/1.8/test/unit/autorunner.rb:13:in  
`run'
         from /usr/local/lib/ruby/1.8/test/unit.rb:285
         from test/unit/product_test.rb:11

I am lost here. Does that ring any bell? Tests run fine with a  
regular SQLite database.

-- fxn

"We all agree on the necessity of compromise.  We just can't agree on
when it's necessary to compromise."
     -- Larry Wall in comp.lang.perl



Reply | Threaded
Open this post in threaded view
|

Re: OT: in-memory for testing in Rails

D. Richard Hipp
Xavier Noria <[hidden email]> wrote:

> I asked this in a couple of Rails places without luck. I guess this  
> is actually related to Rails, just ask it here in case someone knows  
> about it.
>
> The file config/database.yml rails generates has as SQLite database  
> for testing ":memory:", but the simplest of the tests in the Agile  
> book does not work, it produces this trace:
>
> % ruby test/unit/product_test.rb
> Loaded suite test/unit/product_test
> Started
> E/usr/local/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.1.0/lib/sqlite3/
> errors.rb:94:in `check': cannot rollback - no transaction is active  

You're right.  This question is really rails specific.

The error you are getting from SQLite indicates that you
attempted to execute ROLLBACK on a connection that did not
have a current transaction.  The ":memory:" and disk-based
database should work identically in this regard.  I cannot
imagine what the difference might be.  But whatever it is,
this is not a serious error.  You can ignore it if you want.
You database is not endangered.

I do not know how the ruby bindings for SQLite work.  But in
TCL, one typically avoids explicit use of BEGIN, COMMIT, and
ROLLBACK.  Instead, you do this:

   db transaction {
     # lots of other code here
   }

The "db" is the database connection object.  Where the comment
is, you put in lots of code that reads and writes the database
and/or does other things.  If no transaction was active when
the "transaction" method begins, then a new transaction is started.
The transaction automatically commits at the end of the code block
or rolls back if any statement within the code block throws and
exception.  If another transaction was already active when the
transaction method runs, then it just runs the code block - it
becomes a no-op.  In this way, transactions appear to nest.

The point here is that it is impossible to exit the code block
in the "transaction" method without either committing or
rolling back if those are appropriate actions.  Even if exceptions
get thrown, the right thing happens.  You cannot have a logic
error that causes a ROLLBACK or COMMIT to occur at the wrong
time.

I'm wondering if a similar mechanism exists in Ruby.  And if
not, can it be added.  If it does exist, I suggest you use it
and then your problem will likely go away, whatever it is.

--
D. Richard Hipp <[hidden email]>