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