You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-dev@db.apache.org by Manjula G Kutty <ma...@gmail.com> on 2007/01/31 21:32:47 UTC

Junit test question

Hi,

I'm very new to the junit testing. So I picked lang/currentof.java as my 
first test to convert to junit. I did it with the very little knowledge 
I have and also with the help of the Wiki.  I got the test running to 
some extend but then I get some errors on the testUpdate. The error says 
"Invalid cursor state" . I tried using printf to see how the control 
goes and I could see the number of rows expected and got are 0. So it 
should come out of the  verifycount method, but it is not. There may be 
3 reasons for this. Either I didn't understand the test fully or did 
something wrong while converting or there may be bug . Can someone 
please review the attached code(I know it is not a very clean code) and 
let me know what went wrong??

One more question where will  the test database gets created? Even the 
test fails will the teardown method deletes all tables? If so is there a 
mechanism to access the database or copy the database instance when the 
test went wrong?

Thanks in advance
Manjula

Re: Junit test question

Posted by Mamta Satoor <ms...@gmail.com>.
Manjula, I realize this is still work in progress but just something that I
learnt while writing my first junit test. The  junit test class name should
end with Test. eg derbynet/ShutDownDBWhenNSShutsDownTest.java,
derbynet/PrepareStatementTest.java

Mamta

On 1/31/07, Manjula G Kutty <ma...@gmail.com> wrote:
>
> Hi,
>
> I'm very new to the junit testing. So I picked lang/currentof.java as my
> first test to convert to junit. I did it with the very little knowledge
> I have and also with the help of the Wiki.  I got the test running to
> some extend but then I get some errors on the testUpdate. The error says
> "Invalid cursor state" . I tried using printf to see how the control
> goes and I could see the number of rows expected and got are 0. So it
> should come out of the  verifycount method, but it is not. There may be
> 3 reasons for this. Either I didn't understand the test fully or did
> something wrong while converting or there may be bug . Can someone
> please review the attached code(I know it is not a very clean code) and
> let me know what went wrong??
>
> One more question where will  the test database gets created? Even the
> test fails will the teardown method deletes all tables? If so is there a
> mechanism to access the database or copy the database instance when the
> test went wrong?
>
> Thanks in advance
> Manjula
>
>
> package org.apache.derbyTesting.functionTests.tests.lang;
>
> import java.sql.*;
> import junit.framework.Test;
> import junit.framework.TestSuite;
>
> import org.apache.derbyTesting.junit.BaseJDBCTestCase;
> import org.apache.derbyTesting.junit.CleanDatabaseTestSetup;
>
> public class CurrentOfJunit extends BaseJDBCTestCase{
>        private static boolean passed = false;
>
>        public CurrentOfJunit(String name)
>            {
>                super(name);
>            }
>
>        public static Test suite() {
>                TestSuite suite = new TestSuite();
>            if (usingEmbedded()) {
>                suite.addTestSuite(CurrentOfJunit.class);
>            return new CleanDatabaseTestSetup(suite);
>            }
>            return suite;
>            }
>        protected void setUp() throws SQLException
>        {
>            getConnection().setAutoCommit(false);
>            Statement stmt = createStatement();
>            stmt.executeUpdate("create table t (i int, c char(50))");
>            stmt.executeUpdate("create table s (i int, c char(50))");
>            stmt.close();
>            commit();
>        }
>        protected void tearDown() throws Exception
>        {
>                Statement stmt = createStatement();
>                verifyCount("drop table t",
>                            stmt.executeUpdate("drop table t"),
>                                0);
>
>                verifyCount("drop table s",
>                            stmt.executeUpdate("drop table s"),
>                                0);
>                stmt.close();
>        commit();
>        super.tearDown();
>    }
>        public void rowCount(boolean first) throws SQLException{
>                Statement stmt = createStatement();
>                if(!first){
>                        verifyBoolean(
>                                        stmt.execute("delete from t"),
>                                        false);
>
>                }
>                        verifyCount("insert into t values (1956, 'hello
> world')",
>                            stmt.executeUpdate("insert into t values (1956,
> 'hello world')"),
>                                1);
>
>                        verifyCount("insert into t values (456, 'hi
> yourself')",
>                            stmt.executeUpdate("insert into t values (456,
> 'hi yourself')"),
>                                1);
>
>                        verifyCount("insert into t values (180, 'rubber
> ducky')",
>                            stmt.executeUpdate("insert into t values (180,
> 'rubber ducky')"),
>                                1);
>
>                        verifyCount("insert into t values (3, 'you are the
> one')",
>                            stmt.executeUpdate("insert into t values (3,
> 'you are the one')"),
>                                1);
>
>        }
>        public  void testDelete() throws SQLException {
>                PreparedStatement select, delete;
>                Statement select2, delete2;
>                ResultSet cursor;
>                int startCount, endCount;
>                boolean caught;
>                rowCount(true);
>                startCount = countRows("select i, c from t for read only");
>                // because there is no order by (nor can there be)
>                // the fact that this test prints out rows may someday
>                // be a problem.  When that day comes, the row printing
>                // can (should) be removed from this test.
>
>                select = prepareStatement("select i, c from t for update");
>                cursor = select.executeQuery(); // cursor is now open
>
>                // would like to test a delete attempt before the cursor
>                // is open, but finagling to get the cursor name would
>                // destroy the spirit of the rest of the tests,
>                // which want to operate against the generated name.
>
>                // TEST: cursor and target table mismatch
>                caught = false;
>                try {
>                        delete = prepareStatement("delete from s where
> current of "+
>
> cursor.getCursorName());
>                } catch (SQLException se) {
>
>                        String m = se.getSQLState();
>                        assertTrue("42X28" == m);
>                        caught= true;
>                }
> //               TEST: find the cursor during compilation
>                delete = prepareStatement("delete from t where current of
> "+
>
> cursor.getCursorName());
>
>                // TEST: delete before the cursor is on a row
>                caught = false;
>                try {
>                        delete.executeUpdate();
>                } catch (SQLException se) {
>                        String m = se.getSQLState();
>                        assertTrue("24000" == m);
>                        caught= true;
>                }
> //       TEST: find the cursor during execution and it is on a row
>                nextRow(cursor);
>                verifyCount("delete, ok", delete.executeUpdate(),
>                        1);
>                caught = false;
>
> //               skip a row and delete another row so that two rows will
>                // have been removed from the table when we are done.
>                nextRow(cursor); // skip this row
>                nextRow(cursor);
>
>                verifyCount("<delete after skipping>",
>                    delete.executeUpdate(),
>                        1);
>
>                // TEST: delete past the last row
>                nextRow(cursor); // skip this row
>                verifyBoolean(cursor.next(), false); // past last row now
>                caught = false;
>                try {
>                        delete.executeUpdate(); // no current row / closed
>                } catch (SQLException se) {
>                        String m = se.getSQLState();
>                        //System.out.println("Sql state got :"+ m);
>                        assertTrue("24000" == m);
>                        caught= true;
>                }
> //       TEST: delete off a closed cursor
>                // Once this is closed then the cursor no longer exists.
>                cursor.close();
>                caught = false;
>                try {
>                        delete.executeUpdate();
>                } catch (SQLException se) {
>                        String m = se.getSQLState();
>                        //System.out.println("Sql state got :"+ m);
>                        //why assertTrue is failing here?
>                        assertFalse("XCL07" == m ||"42X30" == m);
>                        //assertTrue("42X30" == m);
>                        caught= true;
>                        //if (!caught)
>                        //      throw se;
>                }
>                endCount = countRows ("select i, c from t for read only");
>                verifyCount("startCount-endCount", startCount-endCount,2);
>
>                // TEST: no cursor with that name exists
>                delete2 = createStatement();
>                caught = false;
>                try {
>                        delete2.execute("delete from t where current of
> nosuchcursor");
>                } catch (SQLException se) {
>                        String m = se.getSQLState();
>                        assertTrue("42X30" == m);
>                        caught= true;
>                        //if (!caught)
>                        //      throw se;
>                }
>                delete.close();
>                delete2.close();
>                select.close();
>
>                // TEST: attempt to do positioned delete before cursor
> execute'd
>                // TBD
>
>        }
>        public  void testUpdate() throws SQLException {
>                PreparedStatement select = null;
>                PreparedStatement update = null;
>                Statement select2, update2;
>                ResultSet cursor = null;
>                int startCount, endCount;
>                boolean caught;
>
>                // these are basic tests without a where clause on the
> select.
>                // all rows are in and stay in the cursor's set when
> updated.
>
>                // because there is no order by (nor can there be)
>                // the fact that this test prints out rows may someday
>                // be a problem.  When that day comes, the row printing
>                // can (should) be removed from this test.
>
>                endCount = countRows ("select i, c from t for read only");
>                // TEST: Updated column not found in for update of list
>                caught = false;
>                try {
>                        select = prepareStatement("select I, C from t for
> update of I");
>                        cursor = select.executeQuery(); // cursor is now
> open
>                        update = prepareStatement(
>                                                        "update t set C =
> 'abcde' where current of " +
>
> cursor.getCursorName());
>                } catch (SQLException se) {
>                        String m = se.getSQLState();
>                        assertTrue("42X31" == m);
>                        caught= true;
>                }
>                cursor.close();
>                select.close();
>
>                // TEST: Update of cursor declared READ ONLY
>                caught = false;
>                try {
>                        select = prepareStatement("select I, C from t for
> read only");
>                        cursor = select.executeQuery(); // cursor is now
> open
>                        assertTrue (cursor.getCursorName() == null);
>                        caught=true;
>                } catch (SQLException se) {
>                        String m = se.getSQLState();
>                        //JDBCDisplayUtil.ShowSQLException(System.out,se);
>                        throw se;
>                }
>                cursor.close();
>                select.close();
>
>                // TEST: Update of cursor declared FETCH ONLY
>                caught = false;
>                try {
>                        select = prepareStatement("select I, C from t for
> fetch only");
>                        cursor = select.executeQuery(); // cursor is now
> open
>                        assertTrue(cursor.getCursorName() == null);
>                        caught = true;
>
>                } catch (SQLException se) {
>                        String m = se.getSQLState();
>                        //JDBCDisplayUtil.ShowSQLException(System.out,se);
>                        throw se;
>                }
>                cursor.close();
>                select.close();
>
>                // TEST: Update of cursor with a union
>                caught = false;
>                try {
>                        select = prepareStatement("select I, C from t union
> all select I, C from t");
>                        cursor = select.executeQuery(); // cursor is now
> open
>                        assertTrue(cursor.getCursorName() == null);
>                        caught = true;
>
>                } catch (SQLException se) {
>                        //JDBCDisplayUtil.ShowSQLException(System.out,se);
>                        String m = se.getSQLState();
>                        throw se;
>                }
>                /*finally {
>                        if (! caught)
>                                System.out.println("FAIL: update of union
> cursor not caught");
>                }*/
>                cursor.close();
>                select.close();
>
>
>                // TEST: Update of cursor with a join
>                caught = false;
>                try {
>                        select = prepareStatement("select t1.I, t1.C from t
> t1, t t2 where t1.I = t2.I");
>                        cursor = select.executeQuery(); // cursor is now
> open
>                        assertTrue (cursor.getCursorName() == null);
>                        caught=true;
>                } catch (SQLException se) {
>                        String m = se.getSQLState();
>                        //JDBCDisplayUtil.ShowSQLException(System.out,se);
>                        throw se;
>                } /*finally {
>                        if (! caught)
>                                System.out.println("FAIL: update of join
> cursor not caught");
>                }*/
>                cursor.close();
>                select.close();
>
>                // TEST: Update of cursor with a derived table
>                caught = false;
>                try {
>                        select = prepareStatement("select I, C from (select
> * from t) t1");
>                        cursor = select.executeQuery(); // cursor is now
> open
>                        assertTrue(cursor.getCursorName() == null);
>                        caught=true;
>                } catch (SQLException se) {
>                        String m = se.getSQLState();
>                        //JDBCDisplayUtil.ShowSQLException(System.out,se);
>                        throw se;
>                } finally {
>                        if (! caught)
>                                System.out.println("FAIL: update of derived
> table cursor not caught");
>                }
>                cursor.close();
>                select.close();
>
>                // TEST: Update of cursor with a values clause
>                caught = false;
>                try {
>                        select = prepareStatement("values (1, 2, 3)");
>                        cursor = select.executeQuery(); // cursor is now
> open
>                        assertTrue (cursor.getCursorName() == null);
>                        caught=true;
>                } catch (SQLException se) {
>                        String m = se.getSQLState();
>                        //JDBCDisplayUtil.ShowSQLException(System.out,se);
>                        throw se;
>                } /*finally {
>                        if (! caught)
>                                System.out.println("FAIL: update of values
> clause cursor not caught");
>                }*/
>                cursor.close();
>                select.close();
>
>                // TEST: Update of cursor with a subquery
>                caught = false;
>                try {
>                        select = prepareStatement("select I, C from t where
> I in (select I from t)");
>                        cursor = select.executeQuery(); // cursor is now
> open
>                        assertTrue (cursor.getCursorName() == null);
>                        caught=true;
>                } catch (SQLException se) {
>                        //JDBCDisplayUtil.ShowSQLException(System.out,se);
>                        throw se;
>                } /*finally {
>                        if (! caught)
>                                System.out.println("FAIL: update of
> subquery cursor not caught");
>                }*/
>                cursor.close();
>                select.close();
>
>                select = prepareStatement("select I, C from t for update");
>                cursor = select.executeQuery(); // cursor is now open
>
>                // would like to test a update attempt before the cursor
>                // is open, but finagling to get the cursor name would
>                // destroy the spirit of the rest of the tests,
>                // which want to operate against the generated name.
>
>                // TEST: cursor and target table mismatch
>                caught = false;
>
>                try {
>                        update = prepareStatement("update s set i=1 where
> current of "+
>
> cursor.getCursorName());
>                } catch (SQLException se) {
>                        //JDBCDisplayUtil.ShowSQLException(System.out,se);
>                        String m = se.getSQLState();
>                        assertTrue ("42X29"==m);
>                        caught=true;
>                } /*finally {
>                        if (! caught)
>                                System.out.println("FAIL: update table and
> cursor table mismatch not caught");
>                }*/
>                // TEST: find the cursor during compilation
>                update = prepareStatement(
>                    "update t set i=i+10, c='Gumby was here' where current
> of "+
>                        cursor.getCursorName());
>
>                // TEST: update before the cursor is on a row
>                caught = false;
>                try {
>                        verifyCount("update before the cursor",
> update.executeUpdate(), 0); // no current row / closed
>                } catch (SQLException se) {
>                        String m = se.getSQLState();
>                        //JDBCDisplayUtil.ShowSQLException(System.out,se);
>                        assertTrue ("24000"==m);
>                        caught = true;
>                        }
>                 /*finally {
>                        if (! caught)
>                                System.out.println("FAIL: No error from
> update on cursor before first row");
>                }*/
>
>                // TEST: find the cursor during execution and it is on a
> row
>                nextRow(cursor);
>                System.out.println("you are here");
>                verifyCount("update on row", update.executeUpdate(), 1);
>
>                // TEST: update an already updated row; expect it to
> succeed.
>                // will it have a cumulative effect?
>                verifyCount("2nd update on row", update.executeUpdate(),
> 1);
>
>                // skip a row and update another row so that two rows will
>                // have been removed from the table when we are done.
>                nextRow(cursor); // skip this row
>                nextRow(cursor);
>
>                verifyCount( "update after skipping", update.executeUpdate(),
> 1);
>
>                // TEST: update past the last row
>                nextRow(cursor); // skip this row
>                verifyBoolean(cursor.next(), false); // past last row now
>                caught = false;
>                try {
>                        verifyCount("update: no current row",
> update.executeUpdate(), 0); // no current row / closed
>                } catch (SQLException se) {
>                        String m = se.getSQLState();
>                        //JDBCDisplayUtil.ShowSQLException(System.out,se);
>                        assertTrue("24000"==m);
>                        caught = true;
>
>                } /*finally {
>                        if (! caught)
>                                System.out.println("FAIL: No error from
> update on cursor past last row");
>                }*/
>
>                // TEST: update off a closed cursor
>                cursor.close();
>                select.close();
>                caught = false;
>                try {
>                        verifyCount("update on closed cursor",
> update.executeUpdate(),
>                                                0);
>                } catch (SQLException se) {
>                        String m = se.getSQLState();
>                        //JDBCDisplayUtil.ShowSQLException(System.out,se);
>                        assertTrue ("XCL07"==m ||"42X30"==m);
>                        caught = true;
>
>                } /*finally {
>                        if (! caught)
>                                System.out.println("FAIL: No error from
> update on closed cursor");
>                }*/
>                update.close();
>
>                // TEST: no cursor with that name exists
>                update2 = createStatement();
>                caught = false;
>                try {
>                        update2.execute("update t set i=1 where current of
> nosuchcursor");
>                } catch (SQLException se) {
>                        String m = se.getSQLState();
>                        //JDBCDisplayUtil.ShowSQLException(System.out,se);
>                        assertTrue("42X30"==m);
>                        caught = true;
>                } /*finally {
>                        if (! caught)
>                                System.out.println("FAIL: No error from
> update on nonexistent cursor");
>                }*/
>
>                endCount = countRows ("select i, c from t for read only");
>                //System.out.println("Have "+endCount+" rows in table at
> end");
>
>                // TEST: attempt to do positioned update before cursor
> execute'd
>                // TBD
>
>
>                // TEST closing a cursor will close the related update
>                bug4395("CS4395"); // Application provided cursor name
>                bug4395(null); // system provided cursor name
>
>
>                System.out.println("PASS: update test complete");
>        }
>
>
>        private static void verifyCount(String text, int count, int expect)
> throws SQLException {
>        if (count!=expect) {
>                assertFalse (expect == count);
>                        //throw new SQLException("Wrong number of rows
> returned");
>        }
>        else
>                assertTrue(expect==count);
>
>        }
>        private static void verifyBoolean(boolean got, boolean expect)
> throws SQLException {
>                if (got!=expect) {
>                        assertFalse (expect == got);
>                        //throw new SQLException("Wrong boolean returned");
>                }
>                else
>                        assertTrue(expect==got);
>
>        }
>        static void nextRow(ResultSet r) throws SQLException {
>                verifyBoolean(r.next(), true);
>        }
>
>        private int countRows(String query) throws SQLException {
>                Statement select = createStatement();
>                ResultSet counter = select.executeQuery(query);
>                int count = 0;
>
>                while (counter.next()) {
>                        count++;
>                }
>                counter.close();
>                select.close();
>
>                return count;
>        }
>
>        private  void bug4395(String cursorName) throws SQLException {
>
>                System.out.println("bug4395 Cursor Name " + (cursorName ==
> null ? "System Generated" : "Application Defined"));
>
>                PreparedStatement select = prepareStatement("select I, C
> from t for update");
>                if (cursorName != null)
>                        select.setCursorName(cursorName);
>
>                ResultSet cursor = select.executeQuery(); // cursor is now
> open
>                // TEST: find the cursor during compilation
>                cursorName = cursor.getCursorName();
>                PreparedStatement update = prepareStatement("update t set
> i=i+?, c=? where current of "+
>                        cursorName);
>
>                nextRow(cursor);
>                update.setInt(1, 10);
>                update.setString(2, "Dan was here");
>                verifyCount("update: valid update", update.executeUpdate(),
> 1);
>                cursor.close();
>
>                // now prepare the a cursor with the same name but only
> column I for update
>                PreparedStatement selectdd = prepareStatement("select I, C
> from t for update of I");
>                selectdd.setCursorName(cursorName);
>                cursor = selectdd.executeQuery();
>                nextRow(cursor);
>
>                try {
>                        update.setInt(1, 7);
>                        update.setString(2, "no update");
>                        update.executeUpdate();
>                        } catch (SQLException se) {
>                        String m = se.getSQLState();
>                        //JDBCDisplayUtil.ShowSQLException(System.out,se);
>                        assertTrue ("42X31"==m);
>                }
>
>                cursor.close();
>                cursor = selectdd.executeQuery();
>                nextRow(cursor);
>                cursor.close();
>
>        }
> }
>
>
>

Re: Junit test question

Posted by Manjula G Kutty <ma...@gmail.com>.
Daniel John Debrunner wrote:

> Manjula G Kutty wrote:
>
>> Hi,
>>
>> I'm very new to the junit testing. So I picked lang/currentof.java as 
>> my first test to convert to junit. I did it with the very little 
>> knowledge I have and also with the help of the Wiki.  I got the test 
>> running to some extend but then I get some errors on the testUpdate. 
>> The error says "Invalid cursor state" . I tried using printf to see 
>> how the control goes and I could see the number of rows expected and 
>> got are 0. So it should come out of the  verifycount method, but it 
>> is not. There may be 3 reasons for this. Either I didn't understand 
>> the test fully or did something wrong while converting or there may 
>> be bug . Can someone please review the attached code(I know it is not 
>> a very clean code) and let me know what went wrong??
>
>
> One of the possibly unexpected facts about Junit when coming from the 
> old derby test harness is understanding the setup and tearDown methods 
> of a test class.  A test class contains fixtures, methods that start 
> with 'test' which are individual test cases. The setup and tearDown in 
> a test class are run for *each* fixture, thus I think twice in this 
> class, once for testUpdate() and once for testDelete(). I think a 
> common mistake is to assume they are run once for all the fixtures. 
> Could that be the case here?
>
> Another issue is that the order of fixtures is not guaranteed when 
> adding a suite using MyTest.class. This is intentional since fixtures 
> should be standalone test cases, thus if your test depends on 
> testUpdate() running before testDelete() you may see intermittant 
> problems.
>
>> One more question where will  the test database gets created? Even 
>> the test fails will the teardown method deletes all tables? If so is 
>> there a mechanism to access the database or copy the database 
>> instance when the test went wrong?
>
>
> Nothing exists at the moment, apart from working in a debugger. Please 
> feel free to implement something.
>
> Dan.
>
>
Here is  some information I gathered during the process of this test 
conversion. Thought it will be useful to people like me who are new to 
the junit world. Please feel free to add more information and also 
correct if I went wrong in any place.

The Wiki pages available in the Apache Derby site is very useful to a 
get initial startup.

setup and teardown methods will run per fixture. not once for the whole 
test.
By default all tests should be able to run in embedded or N/W server 
mode, without much user intervention

Most of the lang tests needs to be run with only embedded to avoid the 
overhead of testduration. There is no point in running the same tests
against networkserver if the test is doing simple SQL query tests. But 
tests for hold cursors and updateableResultSets are good candidates for 
the both.

There are some more Assert methods in the java/testing/junit package 
which can be used for most of SQL tests, like for getting the numberof 
rows updated for a prepared statement execution
you can use assertUpdateCount(PreparedStatement, rows expected); If the 
number of rows returned are not equal to the rows expected, the test 
will fail.

You can get rid of most of the try catch block with the assert methods. 
I used try/catch methods only for negative tests, where I have to catch 
the SQL exception. which can also be eliminated using the 
assertStatementError() method
To catch the SQLException you can use assertSQLState() method

If you are using eclipse for the test development then click on the 
class name and you can see all the methods in the right most tab and if 
you sort them you can view all the assert methods together.
Also there is a very good java doc for the Assert class. you can find it 
at http://junit.sourceforge.net/javadoc/junit/framework/Assert.html

It will be nice if we can add a functionality to keep the database as it 
is if the one test fails.

----will add more later

Thanks,
Manjula.


Re: Junit test question

Posted by Daniel John Debrunner <dj...@apache.org>.
Manjula G Kutty wrote:
> Hi,
> 
> I'm very new to the junit testing. So I picked lang/currentof.java as my 
> first test to convert to junit. I did it with the very little knowledge 
> I have and also with the help of the Wiki.  I got the test running to 
> some extend but then I get some errors on the testUpdate. The error says 
> "Invalid cursor state" . I tried using printf to see how the control 
> goes and I could see the number of rows expected and got are 0. So it 
> should come out of the  verifycount method, but it is not. There may be 
> 3 reasons for this. Either I didn't understand the test fully or did 
> something wrong while converting or there may be bug . Can someone 
> please review the attached code(I know it is not a very clean code) and 
> let me know what went wrong??

One of the possibly unexpected facts about Junit when coming from the 
old derby test harness is understanding the setup and tearDown methods 
of a test class.  A test class contains fixtures, methods that start 
with 'test' which are individual test cases. The setup and tearDown in a 
test class are run for *each* fixture, thus I think twice in this class, 
once for testUpdate() and once for testDelete(). I think a common 
mistake is to assume they are run once for all the fixtures. Could that 
be the case here?

Another issue is that the order of fixtures is not guaranteed when 
adding a suite using MyTest.class. This is intentional since fixtures 
should be standalone test cases, thus if your test depends on 
testUpdate() running before testDelete() you may see intermittant problems.

> One more question where will  the test database gets created? Even the 
> test fails will the teardown method deletes all tables? If so is there a 
> mechanism to access the database or copy the database instance when the 
> test went wrong?

Nothing exists at the moment, apart from working in a debugger. Please 
feel free to implement something.

Dan.