Skip to content

Instantly share code, notes, and snippets.

@Sovetnikov
Last active December 19, 2016 09:28
Show Gist options
  • Save Sovetnikov/04343fee7516a501d79b93250922b675 to your computer and use it in GitHub Desktop.
Save Sovetnikov/04343fee7516a501d79b93250922b675 to your computer and use it in GitHub Desktop.
import logging
import os
ABSOLUTE_PATH = lambda x: os.path.abspath(os.path.join(os.path.abspath(os.path.dirname(__file__)), x))
# For Django 1.7.7 sqlite and spatialite
# Uses monkeypatch
#
# Runs tests as:
# 1. Create initial db and apply all migrations if it does not exists
# 2. Apply any unapplied migrations to initial db if it exists
# 3. Copy initial db file to a new one
# 4. Run tests with a new db created via copy
# Use init_fast_sqlite_test at end of settings.py as:
# if len(sys.argv) > 1 and sys.argv[1] == "test":
# init_fast_sqlite_test(sys.modules[__name__])
def init_fast_sqlite_test(settings, spatialite=False):
if 'cachalot' in settings.INSTALLED_APPS:
settings.INSTALLED_APPS.remove('cachalot')
logging.disable(logging.CRITICAL)
settings.PASSWORD_HASHERS = (
'django.contrib.auth.hashers.MD5PasswordHasher',
)
settings.DEBUG = False
settings.TEMPLATE_DEBUG = False
if spatialite:
settings.SPATIALITE_SQL = ABSOLUTE_PATH('init_spatialite-2.3.sql')
settings.SPATIALITE_LIBRARY_PATH = 'libspatialite-1'
settings.DATABASES['default'] = {
'ENGINE': 'django.contrib.gis.db.backends.spatialite' if spatialite else 'django.db.backends.sqlite3',
'NAME': ABSOLUTE_PATH('../test_db.sqlite'),
'TEST': {'NAME': ABSOLUTE_PATH('../test_db.sqlite')}
}
def _sqlite3_create_test_db(self, verbosity, autoclobber):
# Just not delete any db here
test_database_name = self._get_test_db_name()
return test_database_name
from django.db.backends.sqlite3.creation import DatabaseCreation
# Just to prevent database deletion
DatabaseCreation._create_test_db = _sqlite3_create_test_db
def _spatialite_create_test_db(self, verbosity=1, autoclobber=False, serialize=True):
"""
Creates a test database, prompting the user for confirmation if the
database already exists. Returns the name of the test database created.
This method is overloaded to load up the SpatiaLite initialization
SQL prior to calling the `migrate` command.
"""
# Don't import django.core.management if it isn't needed.
from django.core.management import call_command
test_database_name = self._get_test_db_name()
if verbosity >= 1:
test_db_repr = ''
if verbosity >= 2:
test_db_repr = " ('%s')" % test_database_name
print("Creating test database for alias '%s'%s..." % (self.connection.alias, test_db_repr))
# Is file there?
db_exists = os.access(test_database_name, os.F_OK)
self._create_test_db(verbosity, autoclobber)
self.connection.close()
self.connection.settings_dict["NAME"] = test_database_name
# Need to load the SpatiaLite initialization SQL before running `migrate`.
if spatialite and not db_exists:
# Is file exists - no need to initialize spatialite again, or it will raise
self.load_spatialite_sql()
# Report migrate messages at one level lower than that requested.
# This ensures we don't get flooded with messages during testing
# (unless you really ask to be flooded)
# Migrating our initial db, to ensure db structure actual
# Changed test_flush to False, because we do not need to flush any, db is ready for us
call_command('migrate',
verbosity=max(verbosity - 1, 0),
interactive=False,
database=self.connection.alias,
load_initial_data=False,
test_flush=False)
# We then serialize the current state of the database into a string
# and store it on the connection. This slightly horrific process is so people
# who are testing on databases without transactions or who are using
# a TransactionTestCase still get a clean database on every test run.
if serialize:
self.connection._test_serialized_contents = self.serialize_db_to_string()
if not db_exists:
call_command('createcachetable', database=self.connection.alias)
# Ensure a connection for the side effect of initializing the test database.
self.connection.ensure_connection()
# Just copy sqlite db file to a new one and change connection to it!
# All done, new db file will be removed on tests run end ...
# Original db file will be in place
from shutil import copyfile
new_db_name = self.connection.settings_dict["NAME"] + '_test'
copyfile(self.connection.settings_dict["NAME"], new_db_name)
self.connection.close()
self.connection.settings_dict["NAME"] = new_db_name
return test_database_name
if spatialite:
from django.contrib.gis.db.backends.spatialite.creation import SpatiaLiteCreation as Creation
else:
from django.db.backends.creation import BaseDatabaseCreation as Creation
Creation.create_test_db = _spatialite_create_test_db
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment