0
|
1 """
|
|
2 nose plugin for easy testing of django projects and apps. Sets up a test
|
|
3 database (or schema) and installs apps from test settings file before tests
|
|
4 are run, and tears the test database (or schema) down after all tests are run.
|
|
5 """
|
|
6 __author = 'Jason Pellerin'
|
|
7 __version__ = '0.1'
|
|
8
|
|
9 import atexit
|
|
10 import logging
|
|
11 import os, sys
|
|
12 import re
|
|
13
|
|
14 from nose.plugins import Plugin
|
|
15 import nose.case
|
|
16
|
|
17 # Force settings.py pointer
|
|
18 # search the current working directory and all parent directories to find
|
|
19 # the settings file
|
|
20 from nose.importer import add_path
|
|
21 os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
|
|
22 def get_SETTINGS_PATH():
|
|
23 cwd = os.getcwd()
|
|
24 while cwd:
|
|
25 if 'settings.py' in os.listdir(cwd):
|
|
26 break
|
|
27 cwd = os.path.split(cwd)[0]
|
|
28 if cwd == '/':
|
|
29 return None
|
|
30 return cwd
|
|
31 SETTINGS_PATH = get_SETTINGS_PATH()
|
|
32
|
|
33 log = logging.getLogger('nose.plugins.nosedjango')
|
|
34
|
|
35 class NoseDjango(Plugin):
|
|
36 """
|
|
37 Enable to set up django test environment before running all tests, and
|
|
38 tear it down after all tests. If the django database engine in use is not
|
|
39 sqlite3, one or both of --django-test-db or django-test-schema must be
|
|
40 specified.
|
|
41
|
|
42 Note that your django project must be on PYTHONPATH for the settings file
|
|
43 to be loaded. The plugin will help out by placing the nose working dir
|
|
44 into sys.path if it isn't already there, unless the -P
|
|
45 (--no-path-adjustment) argument is set.
|
|
46 """
|
|
47 name = 'django'
|
|
48
|
|
49 def configure(self, options, conf):
|
|
50 Plugin.configure(self, options, conf)
|
|
51 self.verbosity = conf.verbosity
|
|
52
|
|
53 def begin(self):
|
|
54 """Create the test database and schema, if needed, and switch the
|
|
55 connection over to that database. Then call install() to install
|
|
56 all apps listed in the loaded settings module.
|
|
57 """
|
|
58 # Add the working directory (and any package parents) to sys.path
|
|
59 # before trying to import django modules; otherwise, they won't be
|
|
60 # able to find project.settings if the working dir is project/ or
|
|
61 # project/..
|
|
62
|
|
63 if not SETTINGS_PATH:
|
|
64 sys.stderr.write("Can't find Django settings file!\n")
|
|
65 # short circuit if no settings file can be found
|
|
66 return
|
|
67
|
|
68 if self.conf.addPaths:
|
|
69 map(add_path, self.conf.where)
|
|
70
|
|
71 add_path(SETTINGS_PATH)
|
|
72 sys.path.append(SETTINGS_PATH)
|
|
73 import settings
|
|
74 settings.DEBUG = False # I have no idea why Django does this, but it does
|
|
75 from django.core import mail
|
|
76 self.mail = mail
|
|
77 from django.conf import settings
|
|
78 from django.core import management
|
|
79 from django.test.utils import setup_test_environment
|
|
80 from django.db import connection
|
|
81
|
|
82 self.old_db = settings.DATABASE_NAME
|
|
83
|
|
84 # setup the test env for each test case
|
|
85 setup_test_environment()
|
|
86 connection.creation.create_test_db(verbosity=self.verbosity)
|
|
87
|
|
88 # exit the setup phase and let nose do it's thing
|
|
89
|
|
90 def beforeTest(self, test):
|
|
91
|
|
92 if not SETTINGS_PATH:
|
|
93 # short circuit if no settings file can be found
|
|
94 return
|
|
95
|
|
96 from django.core.management import call_command
|
|
97 call_command('flush', verbosity=0, interactive=False)
|
|
98
|
|
99 if isinstance(test, nose.case.Test) and \
|
|
100 isinstance(test.test, nose.case.MethodTestCase) and \
|
|
101 hasattr(test.context, 'fixtures'):
|
|
102 # We have to use this slightly awkward syntax due to the fact
|
|
103 # that we're using *args and **kwargs together.
|
|
104 call_command('loaddata', *test.context.fixtures, **{'verbosity': 0})
|
|
105 self.mail.outbox = []
|
|
106
|
|
107 def finalize(self, result=None):
|
|
108 """
|
|
109 Clean up any created database and schema.
|
|
110 """
|
|
111 if not SETTINGS_PATH:
|
|
112 # short circuit if no settings file can be found
|
|
113 return
|
|
114
|
|
115 from django.test.utils import teardown_test_environment
|
|
116 from django.db import connection
|
|
117 connection.creation.destroy_test_db(self.old_db, verbosity=self.verbosity)
|
|
118 teardown_test_environment()
|