0

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?

1
  • 1
    I do not know whether this is the cause of your problem but the docs you quote recommend using django.test.TestCase rather than unittest.TestCase when running tests with db access. Commented Jan 16, 2020 at 5:48

1 Answer 1

3

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:

  1. Test database will be created with the same credential as actual but the name will be 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).
  2. Before test execution, the test DB will be in a state as actual with 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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. Using from django.test import TestCase instead of from unittest import TestCase is working perfectly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.