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...
1 parent 528e786 commit 2fbb75708d829ce55546a0ad513d9e2437daa1fb @dcramer dcramer committed with Jeff Balogh Aug 8, 2011
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.