Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses

Re: Automated testing of database classes

by jplindstrom (Monsignor)
on Dec 27, 2004 at 20:47 UTC ( #417632=note: print w/replies, xml ) Need Help??

in reply to Automated testing of database classes

The problem with testing database stuff is that you need a known state which you can run the tests against.

There are a few ways you can do this. Most of them involve having a reference database with known data.

One way to restore the known state is to begin a transaction at the beginning of the test and roll it back at the end of the test. Any changes you made during the test are undone.

The problem with this approach is that the rollback semantics in most databases break this; begin and commit are nested properly but a rollback rolls back the entire transaction, not just the most deeply nested one.

In one project with no legacy code we could use transaction savepoints to "fake" proper rollbacks of only the innermost nesting level. And that made it possible to use a transaction for restoring the database state in all unit tests. (The 1100+ unit tests was a success factor for that project btw). This was for Sybase T-SQL, but the savepoint stuff works for Oracle as well.

One more generic way of providing a known state is to make a snapshot of the database before running the tests and restore it just before each test.

If you can run SQLite this is just a matter of copying the, often very small, database file.

If it's any other database, see if you can't script something with your database's data loader utility.

During the actual testing, I find Test::DatabaseRow very useful. One thing to be wary of is that you may have two different database connections to the database, and depending on the isolation level and transaction state, one database connection may not see changes made using the other database connection. And depending on the locking scheme and isolation level, the two connections may lock each other.


  • Comment on Re: Automated testing of database classes

Replies are listed 'Best First'.
Re^2: Automated testing of database classes
by MrCromeDome (Deacon) on Dec 27, 2004 at 21:56 UTC

    The tranasction savepoints sound interesting . While never having investigated them, I'm imagining that SQL Server (the DBMS I'm stuck with) must have some similar functionality. My original suite of tests was very brute force - add rows that I need for my tests, run the tests, manually delete those rows. On the plus side, I at least verified that the delete functionality in Class::DBI worked as intended ;)

    Up to this point, I've always verified my database tests using Class::DBI, but I think I like using yet another tool to verify my test data. Looks like Test::DatabaseRow will fit that bill nicely. Thanks for the recommendation!

      I can imagine that Sybase and MS SQL Server have identical transaction semantics.

      This only works if you can do it consistently, but here is how to nest transactions and limit the rollback scope so that it matches that of e.g. a procedure:

      begin tran save tran the_procedure_name --modify stuff if ... error ... begin rollback tran the_procedure_name commit tran return 1 end --success commit tran return 0

      You start with beginning a transaction and immediately saving the transaction to a named savepoint. I've asked around and this doesn't seem to incur very much overhead.

      If everything works okay, just commit once to end the outermost transaction.

      If anything goes wrong, first rollback to the named savepoint, then commit the transaction (to make sure it's nested properly).


Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://417632]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others pondering the Monastery: (7)
As of 2021-04-19 07:09 GMT
Find Nodes?
    Voting Booth?

    No recent polls found