Permalink
Browse files

Only create databases when the test suite hints that they are required

* Ensure we dont register tests multiple times.
* Fixes #39 and #40.
  • Loading branch information...
dcramer authored and Jeff Balogh committed Aug 8, 2011
1 parent 528e786 commit 2fbb75708d829ce55546a0ad513d9e2437daa1fb
Showing with 52 additions and 32 deletions.
  1. +52 −32 django_nose/plugin.py
View
@@ -2,9 +2,8 @@
import sys
from django.conf import settings
from django.db import connections, router
from django.db.models import signals
from django.db.models.loading import get_apps, get_models, load_app
from django.db.models.loading import get_apps, load_app
from django.test.testcases import TransactionTestCase
class ResultPlugin(object):
@@ -22,12 +21,19 @@ class ResultPlugin(object):
def finalize(self, result):
self.result = result
class _EmptyClass(object):
pass
class DjangoSetUpPlugin(object):
"""
Configures Django to setup and tear down the environment.
This allows coverage to report on all code imported and used during the
initialisation of the test runner.
Only sets up databases if a single class inherits from
``django.test.testcases.TransactionTestCase``.
Also ensures you don't run the same test case multiple times.
"""
name = "django setup"
enabled = True
@@ -37,10 +43,34 @@ def __init__(self, runner):
self.runner = runner
self.sys_stdout = sys.stdout
self.sys_stderr = sys.stderr
self.needs_db = False
self.started = False
self._registry = set()
def begin(self):
self.add_apps = set()
def wantClass(self, cls):
if issubclass(cls, TransactionTestCase):
self.needs_db = True
if cls in self._registry:
return False
self._registry.add(cls)
def wantMethod(self, method):
if issubclass(method.im_class, TransactionTestCase):
self.needs_db = True
if method in self._registry:
return False
self._registry.add(method)
def wantFunction(self, function):
if function in self._registry:
return False
self._registry.add(function)
def beforeImport(self, filename, module):
# handle case of tests.models
if not os.path.isdir(filename):
@@ -59,45 +89,35 @@ def beforeImport(self, filename, module):
self.add_apps.add(module.rsplit('.', 1)[0])
def prepareTestRunner(self, test):
cur_stdout = sys.stdout
cur_stderr = sys.stderr
sys.stdout = self.sys_stdout
sys.stderr = self.sys_stderr
if self.add_apps:
settings.INSTALLED_APPS = set(settings.INSTALLED_APPS)
for app in self.add_apps:
if app in settings.INSTALLED_APPS:
continue
mod = load_app(app)
if mod:
settings.INSTALLED_APPS.add(app)
settings.INSTALLED_APPS = tuple(settings.INSTALLED_APPS)
sys_stdout = sys.stdout
sys_stderr = sys.stderr
sys.stdout = self.sys_stdout
sys.stderr = self.sys_stderr
settings.INSTALLED_APPS.append(app)
get_apps()
self.runner.setup_test_environment()
# HACK: We need to kill post_syncdb receivers to stop them from sending
# when the databases arent fully ready.
post_syncdb_receivers = signals.post_syncdb.receivers
signals.post_syncdb.receivers = []
self.old_names = self.runner.setup_databases()
signals.post_syncdb.receivers = post_syncdb_receivers
for app in get_apps():
app_models = list(get_models(app, include_auto_created=True))
for db in connections:
all_models = [m for m in app_models
if router.allow_syncdb(db, m)]
if not all_models:
continue
signals.post_syncdb.send(app=app, created_models=all_models,
verbosity=self.runner.verbosity,
db=db, sender=app, interactive=False)
if self.needs_db:
self.old_names = self.runner.setup_databases()
sys.stdout = sys_stdout
sys.stderr = sys_stderr
sys.stdout = cur_stdout
sys.stderr = cur_stderr
self.started = True
def finalize(self, result):
if hasattr(self, 'old_names'):
self.runner.teardown_databases(self.old_names)
if self.started:
if self.needs_db:
self.runner.teardown_databases(self.old_names)
self.runner.teardown_test_environment()

0 comments on commit 2fbb757

Please sign in to comment.