annotate nosedjango/nosedjango.py @ 8:a82369f2574e

http client tests
author Victor Ng <victor@monkeybean.ca>
date Thu, 28 Aug 2008 12:42:31 -0400
parents dfba3a3a4343
children 35178e70f1cd
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 os, sys
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
8 import re
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
9
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
10 from nose.plugins import Plugin
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
11 import nose.case
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
12
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
13 # Force settings.py pointer
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
14 # search the current working directory and all parent directories to find
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
15 # the settings file
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
16 from nose.importer import add_path
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
17 os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
5
22ae9aa457af excercise more bits of the django 1.0b1 test framework
Victor Ng <victor@monkeybean.ca>
parents: 3
diff changeset
18 import re
22ae9aa457af excercise more bits of the django 1.0b1 test framework
Victor Ng <victor@monkeybean.ca>
parents: 3
diff changeset
19 NT_ROOT = re.compile(r"^[a-zA-Z]:\\$")
0
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
20 def get_SETTINGS_PATH():
5
22ae9aa457af excercise more bits of the django 1.0b1 test framework
Victor Ng <victor@monkeybean.ca>
parents: 3
diff changeset
21 '''
22ae9aa457af excercise more bits of the django 1.0b1 test framework
Victor Ng <victor@monkeybean.ca>
parents: 3
diff changeset
22 Hunt down the settings.py module by going up the FS path
22ae9aa457af excercise more bits of the django 1.0b1 test framework
Victor Ng <victor@monkeybean.ca>
parents: 3
diff changeset
23 '''
0
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
24 cwd = os.getcwd()
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
25 while cwd:
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
26 if 'settings.py' in os.listdir(cwd):
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
27 break
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
28 cwd = os.path.split(cwd)[0]
5
22ae9aa457af excercise more bits of the django 1.0b1 test framework
Victor Ng <victor@monkeybean.ca>
parents: 3
diff changeset
29 if os.name == 'nt' and NT_ROOT.match(cwd):
22ae9aa457af excercise more bits of the django 1.0b1 test framework
Victor Ng <victor@monkeybean.ca>
parents: 3
diff changeset
30 return None
22ae9aa457af excercise more bits of the django 1.0b1 test framework
Victor Ng <victor@monkeybean.ca>
parents: 3
diff changeset
31 elif cwd == '/':
0
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
32 return None
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
33 return cwd
5
22ae9aa457af excercise more bits of the django 1.0b1 test framework
Victor Ng <victor@monkeybean.ca>
parents: 3
diff changeset
34
0
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
35 SETTINGS_PATH = get_SETTINGS_PATH()
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
36
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
37
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
38 class NoseDjango(Plugin):
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
39 """
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
40 Enable to set up django test environment before running all tests, and
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
41 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
42 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
43 specified.
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
44
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
45 Note that your django project must be on PYTHONPATH for the settings file
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
46 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
47 into sys.path if it isn't already there, unless the -P
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
48 (--no-path-adjustment) argument is set.
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
49 """
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
50 name = 'django'
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
51
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
52 def configure(self, options, conf):
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
53 Plugin.configure(self, options, conf)
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
54 self.verbosity = conf.verbosity
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
55
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
56 def begin(self):
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
57 """Create the test database and schema, if needed, and switch the
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
58 connection over to that database. Then call install() to install
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
59 all apps listed in the loaded settings module.
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
60 """
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
61 # Add the working directory (and any package parents) to sys.path
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
62 # before trying to import django modules; otherwise, they won't be
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
63 # able to find project.settings if the working dir is project/ or
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
64 # project/..
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
65
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
66 if not SETTINGS_PATH:
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
67 sys.stderr.write("Can't find Django settings file!\n")
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
68 # short circuit if no settings file can be found
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
69 return
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
70
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
71 if self.conf.addPaths:
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
72 map(add_path, self.conf.where)
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
73
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
74 add_path(SETTINGS_PATH)
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
75 sys.path.append(SETTINGS_PATH)
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
76 import settings
7
dfba3a3a4343 Comments re: DEBUG and database flushing
Victor Ng <victor@monkeybean.ca>
parents: 5
diff changeset
77
dfba3a3a4343 Comments re: DEBUG and database flushing
Victor Ng <victor@monkeybean.ca>
parents: 5
diff changeset
78 # Some Django code paths evaluate differently
dfba3a3a4343 Comments re: DEBUG and database flushing
Victor Ng <victor@monkeybean.ca>
parents: 5
diff changeset
79 # between DEBUG and not DEBUG. Example of this include the url
dfba3a3a4343 Comments re: DEBUG and database flushing
Victor Ng <victor@monkeybean.ca>
parents: 5
diff changeset
80 # dispatcher when 404's are hit. Django's own test runner forces DEBUG
dfba3a3a4343 Comments re: DEBUG and database flushing
Victor Ng <victor@monkeybean.ca>
parents: 5
diff changeset
81 # to be off.
dfba3a3a4343 Comments re: DEBUG and database flushing
Victor Ng <victor@monkeybean.ca>
parents: 5
diff changeset
82 settings.DEBUG = False
dfba3a3a4343 Comments re: DEBUG and database flushing
Victor Ng <victor@monkeybean.ca>
parents: 5
diff changeset
83
0
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
84 from django.core import mail
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
85 self.mail = mail
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
86 from django.conf import settings
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
87 from django.core import management
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
88 from django.test.utils import setup_test_environment
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
89 from django.db import connection
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
90
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
91 self.old_db = settings.DATABASE_NAME
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
92
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
93 # setup the test env for each test case
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
94 setup_test_environment()
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
95 connection.creation.create_test_db(verbosity=self.verbosity)
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
96
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
97 # exit the setup phase and let nose do it's thing
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
98
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
99 def beforeTest(self, test):
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
100
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
101 if not SETTINGS_PATH:
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
102 # short circuit if no settings file can be found
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
103 return
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
104
7
dfba3a3a4343 Comments re: DEBUG and database flushing
Victor Ng <victor@monkeybean.ca>
parents: 5
diff changeset
105 # This is a distinctive difference between the NoseDjango
dfba3a3a4343 Comments re: DEBUG and database flushing
Victor Ng <victor@monkeybean.ca>
parents: 5
diff changeset
106 # test runner compared to the plain Django test runner.
dfba3a3a4343 Comments re: DEBUG and database flushing
Victor Ng <victor@monkeybean.ca>
parents: 5
diff changeset
107 # Django uses the standard unittest framework and resets the
dfba3a3a4343 Comments re: DEBUG and database flushing
Victor Ng <victor@monkeybean.ca>
parents: 5
diff changeset
108 # database between each test *suite*. That usually resolves
dfba3a3a4343 Comments re: DEBUG and database flushing
Victor Ng <victor@monkeybean.ca>
parents: 5
diff changeset
109 # into a test module.
dfba3a3a4343 Comments re: DEBUG and database flushing
Victor Ng <victor@monkeybean.ca>
parents: 5
diff changeset
110 #
dfba3a3a4343 Comments re: DEBUG and database flushing
Victor Ng <victor@monkeybean.ca>
parents: 5
diff changeset
111 # The NoseDjango test runner will reset the database between *every*
dfba3a3a4343 Comments re: DEBUG and database flushing
Victor Ng <victor@monkeybean.ca>
parents: 5
diff changeset
112 # test case. This is more in the spirit of unittesting where there is
dfba3a3a4343 Comments re: DEBUG and database flushing
Victor Ng <victor@monkeybean.ca>
parents: 5
diff changeset
113 # no state information passed between individual tests.
dfba3a3a4343 Comments re: DEBUG and database flushing
Victor Ng <victor@monkeybean.ca>
parents: 5
diff changeset
114
0
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
115 from django.core.management import call_command
8
a82369f2574e http client tests
Victor Ng <victor@monkeybean.ca>
parents: 7
diff changeset
116 from django.core.urlresolvers import clear_url_caches
0
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
117 call_command('flush', verbosity=0, interactive=False)
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
118
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
119 if isinstance(test, nose.case.Test) and \
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
120 isinstance(test.test, nose.case.MethodTestCase) and \
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
121 hasattr(test.context, 'fixtures'):
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
122 # We have to use this slightly awkward syntax due to the fact
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
123 # that we're using *args and **kwargs together.
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
124 call_command('loaddata', *test.context.fixtures, **{'verbosity': 0})
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
125 self.mail.outbox = []
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
126
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
127 def finalize(self, result=None):
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
128 """
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
129 Clean up any created database and schema.
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
130 """
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
131 if not SETTINGS_PATH:
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
132 # short circuit if no settings file can be found
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
133 return
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
134
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
135 from django.test.utils import teardown_test_environment
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
136 from django.db import connection
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
137 connection.creation.destroy_test_db(self.old_db, verbosity=self.verbosity)
ff263bdd455e initial checkin
Victor Ng <victor@monkeybean.ca>
parents:
diff changeset
138 teardown_test_environment()