vishnu m c vishnu m c -4 years ago 63
Python Question

Difference between TestCase and TransactionTestCase classes in django test

Can you please anyone explain the difference between TestCase class and TransactionTestCase class. I have read the document but its only saying that TestCase run test in DB transaction and uses rollback to 'undo' the test in the DB and If you need to manually manage transactions within your test, you would need to use django.test.TransactionTestCase.

Will you please help me to understand the actual difference with an example?
I just want to know in what condition the TestCase fails? also whether the rollback are taken place automatically or we have to write statement for rollback?

Please help me

Answer Source

The main difference between TestCase and TransactionTestCase is that TestCase wraps the tests with atomic() blocks ALL THE TIME. From the documentation:

Wraps the tests within two nested atomic() blocks: one for the whole class and one for each test

Now imagine that you have a method that should raise an error if it is not wrapped inside atomic() block. You are trying to write a test for that:

def test_your_method_raises_error_without_atomic_block(self):
    with self.assertRaises(SomeError):
        your_method()

This test will unexpectedly fail! The reason is, you guessed it, TestCase wraps the tests with atomic() blocks ALL THE TIME. Thus, your_method() will not raise an error, which is why this test will fail. In this case, you should use TransactionTestCase to make your test pass.

select_for_update() is a clear case in point:

Evaluating a queryset with select_for_update() in autocommit mode on backends which support SELECT ... FOR UPDATE is a TransactionManagementError error

From the TransactionTestCase documentation:

with TestCase class, you cannot test that a block of code is executing within a transaction, as is required when using select_for_update()

And if we take a look at the documentation of select_for_update(), we see a warning:

Although select_for_update() normally fails in autocommit mode, since TestCase automatically wraps each test in a transaction, calling select_for_update() in a TestCase even outside an atomic() block will (perhaps unexpectedly) pass without raising a TransactionManagementError. To properly test select_for_update() you should use TransactionTestCase.

Hope it helps!

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download