Different db for testing in Django?

DjangoUnit TestingSqlitePostgresql

Django Problem Overview


DATABASES = {
#    'default': {
#        'ENGINE': 'postgresql_psycopg2',
#        ...
#    }
     
    # for unit tests
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'mydatabase'
    }
}

I have two databases: one I'd like to use for unit tests, and one for everything else. Is it possible to configure this in Django 1.2.4?

(The reason I ask is because with postgresql I'm getting the following error:

foo@bar:~/path/$ python manage.py test
Creating test database 'default'...
Got an error creating the test database: permission denied to create database

Type 'yes' if you would like to try deleting the test database 'test_baz', or 'no' to cancel: yes
Destroying old test database...
Got an error recreating the test database: database "test_baz" does not exist

Why could I be getting this error? I guess I don't really care if I can always use SQLite for unit tests, as that works fine.)

Django Solutions


Solution 1 - Django

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

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

Solution 2 - Django

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.

Solution 3 - Django

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',
        },
    },
}

Solution 4 - Django

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

Solution 5 - Django

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]
}

Solution 6 - Django

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

Solution 7 - Django

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.

Solution 8 - Django

You can mirror your db by editing settings.py:

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

Solution 9 - Django

>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

Solution 10 - Django

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNick HeinerView Question on Stackoverflow
Solution 1 - DjangoSam DolanView Answer on Stackoverflow
Solution 2 - DjangoGeoffrey HingView Answer on Stackoverflow
Solution 3 - DjangoLeon MakView Answer on Stackoverflow
Solution 4 - DjangolaffusteView Answer on Stackoverflow
Solution 5 - DjangoCacoView Answer on Stackoverflow
Solution 6 - DjangoMario CorcheroView Answer on Stackoverflow
Solution 7 - DjangomhostView Answer on Stackoverflow
Solution 8 - DjangoEvydeView Answer on Stackoverflow
Solution 9 - DjangoSamkit JainView Answer on Stackoverflow
Solution 10 - DjangoCristian GusellaView Answer on Stackoverflow