Mercurial > nosedjango
diff nosedjango/nosedjango.py @ 0:ff263bdd455e
initial checkin
author | Victor Ng <victor@monkeybean.ca> |
---|---|
date | Thu, 28 Aug 2008 09:44:43 -0400 |
parents | |
children | b761c26773a3 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nosedjango/nosedjango.py Thu Aug 28 09:44:43 2008 -0400 @@ -0,0 +1,118 @@ +""" +nose plugin for easy testing of django projects and apps. Sets up a test +database (or schema) and installs apps from test settings file before tests +are run, and tears the test database (or schema) down after all tests are run. +""" +__author = 'Jason Pellerin' +__version__ = '0.1' + +import atexit +import logging +import os, sys +import re + +from nose.plugins import Plugin +import nose.case + +# Force settings.py pointer +# search the current working directory and all parent directories to find +# the settings file +from nose.importer import add_path +os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' +def get_SETTINGS_PATH(): + cwd = os.getcwd() + while cwd: + if 'settings.py' in os.listdir(cwd): + break + cwd = os.path.split(cwd)[0] + if cwd == '/': + return None + return cwd +SETTINGS_PATH = get_SETTINGS_PATH() + +log = logging.getLogger('nose.plugins.nosedjango') + +class NoseDjango(Plugin): + """ + Enable to set up django test environment before running all tests, and + tear it down after all tests. If the django database engine in use is not + sqlite3, one or both of --django-test-db or django-test-schema must be + specified. + + Note that your django project must be on PYTHONPATH for the settings file + to be loaded. The plugin will help out by placing the nose working dir + into sys.path if it isn't already there, unless the -P + (--no-path-adjustment) argument is set. + """ + name = 'django' + + def configure(self, options, conf): + Plugin.configure(self, options, conf) + self.verbosity = conf.verbosity + + def begin(self): + """Create the test database and schema, if needed, and switch the + connection over to that database. Then call install() to install + all apps listed in the loaded settings module. + """ + # Add the working directory (and any package parents) to sys.path + # before trying to import django modules; otherwise, they won't be + # able to find project.settings if the working dir is project/ or + # project/.. + + if not SETTINGS_PATH: + sys.stderr.write("Can't find Django settings file!\n") + # short circuit if no settings file can be found + return + + if self.conf.addPaths: + map(add_path, self.conf.where) + + add_path(SETTINGS_PATH) + sys.path.append(SETTINGS_PATH) + import settings + settings.DEBUG = False # I have no idea why Django does this, but it does + from django.core import mail + self.mail = mail + from django.conf import settings + from django.core import management + from django.test.utils import setup_test_environment + from django.db import connection + + self.old_db = settings.DATABASE_NAME + + # setup the test env for each test case + setup_test_environment() + connection.creation.create_test_db(verbosity=self.verbosity) + + # exit the setup phase and let nose do it's thing + + def beforeTest(self, test): + + if not SETTINGS_PATH: + # short circuit if no settings file can be found + return + + from django.core.management import call_command + call_command('flush', verbosity=0, interactive=False) + + if isinstance(test, nose.case.Test) and \ + isinstance(test.test, nose.case.MethodTestCase) and \ + hasattr(test.context, 'fixtures'): + # We have to use this slightly awkward syntax due to the fact + # that we're using *args and **kwargs together. + call_command('loaddata', *test.context.fixtures, **{'verbosity': 0}) + self.mail.outbox = [] + + def finalize(self, result=None): + """ + Clean up any created database and schema. + """ + if not SETTINGS_PATH: + # short circuit if no settings file can be found + return + + from django.test.utils import teardown_test_environment + from django.db import connection + connection.creation.destroy_test_db(self.old_db, verbosity=self.verbosity) + teardown_test_environment()