When I run Django tests that inserts data into the database, it will insert to my local db.sqlite3
and preserve it when the tests finishes. I don't want this to happen, and it shouldn't be according to the docs:
Regardless of whether the tests pass or fail, the test databases are destroyed when all the tests have been executed.
My unit test:
from unittest import TestCase
from web.constants import USER_TYPE_CONTRACTOR
from web.models import User
class LoginTestCase(TestCase):
def setUp(self):
self.demo_user_1_username = 'c2'
User.objects.create(username=self.demo_user_1_username, password='c12345678')
def test_user_defaults_to_contractor(self):
demo_user_1 = User.objects.get(username=self.demo_user_1_username)
self.assertEqual(demo_user_1.user_type, USER_TYPE_CONTRACTOR)
def doCleanups(self):
"""Delete demo data from database"""
# I needed to do this as workaround
# demo_user_1 = User.objects.get(username=self.demo_user_1_username)
# demo_user_1.delete()
The user c2
is now in the db.sqlite3
, so when I run the test again, it fails as username c2
already exists.
I've tried to do this in settings.py
:
DATABASES = {
'default': dj_database_url.config(conn_max_age=600)
}
DATABASES['default']['TEST'] = {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'test_db.sqlite3'),
}
But test_db.sqlite3
is not created.
How can I use an in-memory sqlite3 db so it doesn't affect my local db when testing?
The problem here, how @Chris mentioned in direct usage of TestCase
from unitetest
module, the hierarchical chain looks like this:
TestCase->TransactionTestCase->SimpleTestCase->unittest.TestCase
How documentation summaries:
[TestCase] - This is the most common class to use for writing tests in Django. It inherits from TransactionTestCase (and by extension SimpleTestCase). If your Django application doesn’t use a database, use SimpleTestCase.
Here:
When I run Django tests that inserts data into the database, it will insert to my local db.sqlite3 and preserve it when the tests finishes.
NOTE: In your case, tests are using the actual database, which leads to a data loss and population with mock data. Never use such workflow!
Actually, tests mustn't use your actual database at all, by default for sqlite3
backend Django will handle in-memory database, destruction of the database can be controlled using the flag --keepdb
. Generally speaking, the flow is as follows:
test_<actual_db_name>
. It is even possible to access the database between test execution in case if it is not deleted every time after tests have passed (--keepdb
).python manage.py migrate
executed, though you can omit migration execution via overriding MIGRATION_MODULES
env variable.So, the solution is to switch to the django.test.TestCase
usage instead.