[Django]-Different db for testing in Django?

101πŸ‘

βœ…

In your settings.py (or local_settings.py):

import sys
if 'test' in sys.argv:
    DATABASES['default'] = {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'mydatabase'
    }

47πŸ‘

The way I handle this is through having multiple settings files, since I use that to maintain a set of common settings with modifications for each instance. It’s a little more complicated to set up than some of the other solutions, but I needed to do it anyway because I was managing slightly different settings for local development, remote development, staging and production.

https://code.djangoproject.com/wiki/SplitSettings has a number of options for managing settings, and I’ve chosen a practice similar to the one described at https://code.djangoproject.com/wiki/SplitSettings#SimplePackageOrganizationforEnvironments

So, in my Django project directory, I have a settings folder that looks like this:

$ tree settings
settings
β”œβ”€β”€ defaults.py
β”œβ”€β”€ dev.py
β”œβ”€β”€ dev.pyc
β”œβ”€β”€ __init__.py
β”œβ”€β”€ lettuce.py
β”œβ”€β”€ travis.py
β”œβ”€β”€ unittest.py

The common settings are in settings/defaults.py and I import these in my instance settings files. So settings/unittest.py looks like this:

from defaults import *

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'my_database',
    }
} 

Then, when I want to run tests, I just execute:

$ ./manage.py test --settings=settings.unittest

to use sqlite for testing. I’ll use a different settings module if I want to use a different test runner or database configuration.

30πŸ‘

You can specify test database in settings.py. See
https://docs.djangoproject.com/en/3.0/topics/testing/overview/#the-test-database

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'USER': 'mydatabaseuser',
        'NAME': 'mydatabase',
        'TEST': {
            'NAME': 'mytestdatabase',
        },
    },
}

9πŸ‘

I solved this issue simply creating other settings constant DATABASES_AVAILABLE.

DATABASES_AVAILABLE = {
    'main': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'nep',
        'USER': 'user',
        'PASSWORD': 'passwd',
        'HOST': 'localhost',
    },
    'remote': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'nes_dev',
        'USER': 'usr',
        'PASSWORD': 'passwd',
        'HOST': '200.144.254.136',
    },
    'sqlite': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    },
}

# This solves the problem with tests
# Define a system variable called DJANGO_DATABASE_TEST and set it to the
# the database you want
database = os.environ.get('DJANGO_DATABASE_TEST', 'main')
DATABASES = {
    'default': DATABASES_AVAILABLE[database]
}

8πŸ‘

This accelerated dramatically test execution.

import sys

if 'test' in sys.argv:
    DATABASES['default'] = {
        'ENGINE': 'django.db.backends.sqlite3',
        'TEST_CHARSET': 'UTF8', # if your normal db is utf8
        'NAME': ':memory:', # in memory
        'TEST_NAME': ':memory:', # in memory
    }

    DEBUG = False # might accelerate a bit
    TEMPLATE_DEBUG = False

    from django.core.management import call_command
    call_command('syncdb', migrate=True) # tables don't get created automatically for me

5πŸ‘

Though this is already solved…

If your database for tests is just a normal DB:

I think you are not doing unit test since you rely in the database. Anyway, django contains a test type for that (not unitary): django.test.TestCase

You need to derive from django.test.TestCase instead of unittest.TestCase that will create a fresh rehershal database for you that will be destroyed when the test end.

There are interesting explanations/tips about testing with db in the following link
Testing Django Applications

4πŸ‘

You can mirror your db by editing settings.py:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'USER': 'mydatabaseuser',
        'NAME': 'mydatabase',
        'TEST': {
            'MIRROR': 'default',
        },
    },
}

3πŸ‘

If you have access to manually create the database, you could use django-nose as your TEST_RUNNER. Once installed, if you pass the following environment variable, it will not delete and re-create the database.

REUSE_DB=1 ./manage.py test

You can also add the following to settings.py so you don’t have to write REUSE_DB=1 every time you want to run tests:

os.environ['REUSE_DB'] = "1"

Note: this will also leave all your tables in the databases which means test setup will be a little quicker, but you will have to manually update the tables (or delete and re-create the database yourself) when you change your models.

2πŸ‘

I had your same issue. I resolved it just adding in settings.py the TEST value in the database, available in my Django version 4.0.2, in this way:

DATABASES = {
     'default': {
            'ENGINE': 'django.db.backends.postgresql',
            'HOST': host,
            'NAME': name,
            'TEST': {'NAME': 'test_db'},
            'USER': user,
            'PASSWORD': your_password,
    }
}.

This temporary creates db with different name and the conflict is resolved.

1πŸ‘

Why could I be getting this error?

Because of insufficient permissions. You can alter the user permissions by ALTER USER username CREATEDB; after running psql with superuser priviliges.

Example,

$ sudo su - postgres
$ psql
psql (9.3.18)
Type "help" for help.

postgres=# ALTER USER username CREATEDB;
ALTER ROLE

Leave a comment