Reputation: 9720
I have written a test to check the integrity of the data I keep in my fixtures. It is a class inheriting from django.tests.TestCase
, and it declares the fixtures it needs. When I run the methods in this class only, they pass. However, when I run all of my tests, some fixtures from other tests remain in the db, which makes the tests fail. I tried different variants, and for now I am overriding the setUpTestData
class method to kill all db data before my test, but this can't be right. There must be a better way :)
class FixturesTest(TestCase):
fixtures = ["tariff.json"]
@classmethod
def setUpTestData(cls):
TariffModel.objects.all().delete()
def test_tariff_fixtures(self):
"""Check the fixtures for tariffs"""
...
Thanks.
UPD: That said, some of the other tests do load their own fixtures. But I thought they should be dropped between tests.
Upvotes: 2
Views: 1981
Reputation: 492
You can loaddata by invoking call_command
in setUp
, like this you don't have to do any Cleanup
from django.core.management import call_command
class FixturesTest(TestCase):
def setUp(self):
# Load fixtures
call_command('loaddata', 'path/to/tariff.json')
Upvotes: 1
Reputation: 11
I had the same issue which is 2 days late. good news for us, there are several solutions,
Solution 1
Make sure if you are overriding the class method tearDownClass that you call super().tearDownClass()
. If you override tearDownClass()
without calling its super, it will in turn never call TransactionTestCase._post_teardown()
nor TransactionTestCase._fixture_teardown()
. Quoting from the doc string in TransactionTestCase._post_teardown()
:
def _post_teardown(self):
"""
Perform post-test things:
* Flush the contents of the database to leave a clean slate. If the
class has an 'available_apps' attribute, don't fire post_migrate.
* Force-close the connection so the next test gets a clean cursor.
"""
If TestCase.tearDownClass()
is not called via super()
then the database is not reset in between test cases and you will get the dreaded duplicate key exception.
Solution 2
Override TransactionTestCase and set the class variable serialized_rollback = True, like this:
class MyTestCase(TransactionTestCase):
fixtures = ['test-data.json']
serialized_rollback = True
def test_name_goes_here(self):
pass
Quoting from the source:
class TransactionTestCase(SimpleTestCase):
...
# If transactions aren't available, Django will serialize the database
# contents into a fixture during setup and flush and reload them
# during teardown (as flush does not restore data from migrations).
# This can be slow; this flag allows enabling on a per-case basis.
serialized_rollback = False
When serialized_rollback is set to True, Django test runner rolls back any transactions inserted into the database between test cases. And batta bing, batta bang... no more duplicate key errors!
you can follow this link, for more details
Upvotes: -1