annotate nosedjango/nosedjango.py @ 3:b761c26773a3

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