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