GeoDjango users may now use `django.contrib.gis.tests.run_tests` for their `TEST_RUNNER` so that a testing spatial database is properly created; the GeoDjango test suite runner is renamed to `run_gis_tests`.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@8434 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Justin Bronn 2008-08-18 15:58:29 +00:00
parent 62aafd8e30
commit 463b325cb6
2 changed files with 100 additions and 62 deletions

View File

@ -1,8 +1,9 @@
import os, re, sys
from django.conf import settings
from django.core.management import call_command
from django.db import connection
from django.db.backends.creation import TEST_DATABASE_PREFIX
import os, re, sys
def getstatusoutput(cmd):
"A simpler version of getstatusoutput that works on win32 platforms."
@ -57,7 +58,6 @@ def _create_with_cursor(db_name, verbosity=1, autoclobber=False):
cursor.execute(create_sql)
else:
raise Exception('Spatial Database Creation canceled.')
foo = _create_with_cursor
created_regex = re.compile(r'^createdb: database creation failed: ERROR: database ".+" already exists')
def _create_with_shell(db_name, verbosity=1, autoclobber=False):

View File

@ -1,8 +1,10 @@
import sys
from unittest import TestSuite, TextTestRunner
import sys, unittest
from django.conf import settings
if not settings._target: settings.configure()
from django.db import connection
from django.db.models import get_app, get_apps, loading
from django.test.simple import build_suite, build_test
from django.test.utils import setup_test_environment, teardown_test_environment
def geo_suite():
"""
@ -48,56 +50,21 @@ def geo_suite():
if HAS_GEOIP and hasattr(settings, 'GEOIP_PATH'):
test_suite_names.append('test_geoip')
s = TestSuite()
s = unittest.TestSuite()
for test_suite in test_suite_names:
tsuite = getattr(__import__('django.contrib.gis.tests', globals(), locals(), [test_suite]),test_suite)
s.addTest(tsuite.suite())
return s, test_models
def run(verbosity=1):
"Runs the tests that do not require geographic (GEOS, GDAL, etc.) models."
TextTestRunner(verbosity=verbosity).run(geo_suite())
def run_tests(module_list, verbosity=1, interactive=True):
def run_gis_tests(test_labels, **kwargs):
"""
Run the tests that require creation of a spatial database.
In order to run geographic model tests the DATABASE_USER will require
superuser priviliges. To accomplish this outside the `postgres` user,
create your own PostgreSQL database as a user:
(1) Initialize database: `initdb -D /path/to/user/db`
(2) If there's already a Postgres instance on the machine, it will need
to use a different TCP port than 5432. Edit postgresql.conf (in
/path/to/user/db) to change the database port (e.g. `port = 5433`).
(3) Start this database `pg_ctl -D /path/to/user/db start`
On Windows platforms simply use the pgAdmin III utility to add superuser
privileges to your database user.
Make sure your settings.py matches the settings of the user database.
For example, set the same port number (`DATABASE_PORT=5433`).
DATABASE_NAME or TEST_DATABSE_NAME must be set, along with DATABASE_USER.
In settings.py set TEST_RUNNER='django.contrib.gis.tests.run_tests'.
Finally, this assumes that the PostGIS SQL files (lwpostgis.sql and
spatial_ref_sys.sql) are installed in the directory specified by
`pg_config --sharedir` (and defaults to /usr/local/share if that fails).
This behavior is overridden if `POSTGIS_SQL_PATH` is in your settings.
Windows users should set POSTGIS_SQL_PATH manually because the output
of `pg_config` uses paths like 'C:/PROGRA~1/POSTGR~1/..'.
Finally, the tests may be run by invoking `./manage.py test`.
Use this routine as the TEST_RUNNER in your settings in order to run the
GeoDjango test suite. This must be done as a database superuser for
PostGIS, so read the docstring in `run_test()` below for more details.
"""
from django.contrib.gis.db.backend import create_spatial_db
from django.contrib.gis.tests.utils import mysql
from django.db import connection
from django.db.models import loading
# Getting initial values.
old_debug = settings.DEBUG
old_name = settings.DATABASE_NAME
old_installed = settings.INSTALLED_APPS
old_root_urlconf = settings.ROOT_URLCONF
@ -118,12 +85,9 @@ def run_tests(module_list, verbosity=1, interactive=True):
# Setting the URLs.
settings.ROOT_URLCONF = 'django.contrib.gis.tests.urls'
# Want DEBUG to be set to False.
settings.DEBUG = False
# Creating the test suite, adding the test models to INSTALLED_APPS, and
# adding the model test suites to our suite package.
test_suite, test_models = geo_suite()
gis_suite, test_models = geo_suite()
for test_model in test_models:
module_name = 'django.contrib.gis.tests.%s' % test_model
if mysql:
@ -135,8 +99,8 @@ def run_tests(module_list, verbosity=1, interactive=True):
# Getting the model test suite
tsuite = getattr(__import__('django.contrib.gis.tests.%s' % test_model, globals(), locals(), [test_module_name]),
test_module_name)
test_suite.addTest(tsuite.suite())
gis_suite.addTest(tsuite.suite())
# Resetting the loaded flag to take into account what we appended to
# the INSTALLED_APPS (since this routine is invoked through
# django/core/management, it caches the apps; this ensures that syncdb
@ -144,20 +108,94 @@ def run_tests(module_list, verbosity=1, interactive=True):
settings.INSTALLED_APPS = new_installed
loading.cache.loaded = False
# Creating the test spatial database.
create_spatial_db(test=True, verbosity=verbosity)
# Running the tests using the GIS test runner.
result = run_tests(test_labels, suite=gis_suite, **kwargs)
# Executing the tests (including the model tests)
result = TextTestRunner(verbosity=verbosity).run(test_suite)
# Cleaning up, destroying the test spatial database and resetting the INSTALLED_APPS.
connection.creation.destroy_test_db(old_name, verbosity)
settings.DEBUG = old_debug
# Restoring modified settings.
settings.INSTALLED_APPS = old_installed
settings.ROOT_URLCONF = old_root_urlconf
return result
def run_tests(test_labels, verbosity=1, interactive=True, extra_tests=[], suite=None):
"""
This module allows users to run tests for GIS apps that require the creation
of a spatial database. Currently, this is only required for PostgreSQL as
PostGIS needs extra overhead in test database creation.
In order to create a PostGIS database, the DATABASE_USER (or
TEST_DATABASE_USER, if defined) will require superuser priviliges.
To accomplish this outside the `postgres` user, you have a few options:
(A) Make your user a super user:
This may be done at the time the user is created, for example:
$ createuser --superuser <user_name>
Or you may alter the user's role from the SQL shell (assuming this
is done from an existing superuser role):
postgres# ALTER ROLE <user_name> SUPERUSER;
(B) Create your own PostgreSQL database as a local user:
1. Initialize database: `initdb -D /path/to/user/db`
2. If there's already a Postgres instance on the machine, it will need
to use a different TCP port than 5432. Edit postgresql.conf (in
/path/to/user/db) to change the database port (e.g. `port = 5433`).
3. Start this database `pg_ctl -D /path/to/user/db start`
(C) On Windows platforms the pgAdmin III utility may also be used as
a simple way to add superuser privileges to your database user.
The TEST_RUNNER needs to be set in your settings like so:
TEST_RUNNER='django.contrib.gis.tests.run_tests'
Note: This test runner assumes that the PostGIS SQL files ('lwpostgis.sql'
and 'spatial_ref_sys.sql') are installed in the directory specified by
`pg_config --sharedir` (and defaults to /usr/local/share if that fails).
This behavior is overridden if POSTGIS_SQL_PATH is set in your settings.
Windows users should set POSTGIS_SQL_PATH manually because the output
of `pg_config` uses paths like 'C:/PROGRA~1/POSTGR~1/..'.
Finally, the tests may be run by invoking `./manage.py test`.
"""
# The `create_spatial_db` routine abstracts away all the steps needed
# to properly construct a spatial database for the backend.
from django.contrib.gis.db.backend import create_spatial_db
# Setting up for testing.
setup_test_environment()
settings.DEBUG = False
old_name = settings.DATABASE_NAME
# The suite may be passed in manually, e.g., when we run the GeoDjango test,
# we want to build it and pass it in due to some customizations. Otherwise,
# the normal test suite creation process from `django.test.simple.run_tests`
# is used to create the test suite.
if suite is None:
suite = unittest.TestSuite()
if test_labels:
for label in test_labels:
if '.' in label:
suite.addTest(build_test(label))
else:
app = get_app(label)
suite.addTest(build_suite(app))
else:
for app in get_apps():
suite.addTest(build_suite(app))
for test in extra_tests:
suite.addTest(test)
# Creating the test spatial database.
create_spatial_db(test=True, verbosity=verbosity)
# Executing the tests (including the model tests), and destorying the
# test database after the tests have completed.
result = unittest.TextTestRunner(verbosity=verbosity).run(suite)
connection.creation.destroy_test_db(old_name, verbosity)
teardown_test_environment()
# Returning the total failures and errors
return len(result.failures) + len(result.errors)
if __name__ == '__main__':
run()