3 import os
, sys
, traceback
6 import django
.contrib
as contrib
11 from sets
import Set
as set # For Python 2.3
14 CONTRIB_DIR_NAME
= 'django.contrib'
15 MODEL_TESTS_DIR_NAME
= 'modeltests'
16 REGRESSION_TESTS_DIR_NAME
= 'regressiontests'
18 TEST_TEMPLATE_DIR
= 'templates'
20 CONTRIB_DIR
= os
.path
.dirname(contrib
.__file
__)
21 MODEL_TEST_DIR
= os
.path
.join(os
.path
.dirname(__file__
), MODEL_TESTS_DIR_NAME
)
22 REGRESSION_TEST_DIR
= os
.path
.join(os
.path
.dirname(__file__
), REGRESSION_TESTS_DIR_NAME
)
24 ALWAYS_INSTALLED_APPS
= [
25 'django.contrib.contenttypes',
26 'django.contrib.auth',
27 'django.contrib.sites',
28 'django.contrib.flatpages',
29 'django.contrib.redirects',
30 'django.contrib.sessions',
31 'django.contrib.comments',
32 'django.contrib.admin',
35 def get_test_models():
37 for loc
, dirpath
in (MODEL_TESTS_DIR_NAME
, MODEL_TEST_DIR
), (REGRESSION_TESTS_DIR_NAME
, REGRESSION_TEST_DIR
), (CONTRIB_DIR_NAME
, CONTRIB_DIR
):
38 for f
in os
.listdir(dirpath
):
39 if f
.startswith('__init__') or f
.startswith('.') or f
.startswith('sql') or f
.startswith('invalid'):
41 models
.append((loc
, f
))
44 def get_invalid_models():
46 for loc
, dirpath
in (MODEL_TESTS_DIR_NAME
, MODEL_TEST_DIR
), (REGRESSION_TESTS_DIR_NAME
, REGRESSION_TEST_DIR
), (CONTRIB_DIR_NAME
, CONTRIB_DIR
):
47 for f
in os
.listdir(dirpath
):
48 if f
.startswith('__init__') or f
.startswith('.') or f
.startswith('sql'):
50 if f
.startswith('invalid'):
51 models
.append((loc
, f
))
54 class InvalidModelTestCase(unittest
.TestCase
):
55 def __init__(self
, model_label
):
56 unittest
.TestCase
.__init
__(self
)
57 self
.model_label
= model_label
60 from django
.core
.management
.validation
import get_validation_errors
61 from django
.db
.models
.loading
import load_app
62 from cStringIO
import StringIO
65 module
= load_app(self
.model_label
)
67 self
.fail('Unable to load invalid model module')
69 # Make sure sys.stdout is not a tty so that we get errors without
70 # coloring attached (makes matching the results easier). We restore
71 # sys.stderr afterwards.
72 orig_stdout
= sys
.stdout
75 count
= get_validation_errors(s
, module
)
76 sys
.stdout
= orig_stdout
79 actual
= error_log
.split('\n')
80 expected
= module
.model_errors
.split('\n')
82 unexpected
= [err
for err
in actual
if err
not in expected
]
83 missing
= [err
for err
in expected
if err
not in actual
]
85 self
.assert_(not unexpected
, "Unexpected Errors: " + '\n'.join(unexpected
))
86 self
.assert_(not missing
, "Missing Errors: " + '\n'.join(missing
))
88 def django_tests(verbosity
, interactive
, test_labels
):
89 from django
.conf
import settings
91 old_installed_apps
= settings
.INSTALLED_APPS
92 old_test_database_name
= settings
.TEST_DATABASE_NAME
93 old_root_urlconf
= settings
.ROOT_URLCONF
94 old_template_dirs
= settings
.TEMPLATE_DIRS
95 old_use_i18n
= settings
.USE_I18N
96 old_language_code
= settings
.LANGUAGE_CODE
97 old_middleware_classes
= settings
.MIDDLEWARE_CLASSES
99 # Redirect some settings for the duration of these tests.
100 settings
.INSTALLED_APPS
= ALWAYS_INSTALLED_APPS
101 settings
.ROOT_URLCONF
= 'urls'
102 settings
.TEMPLATE_DIRS
= (os
.path
.join(os
.path
.dirname(__file__
), TEST_TEMPLATE_DIR
),)
103 settings
.USE_I18N
= True
104 settings
.LANGUAGE_CODE
= 'en'
105 settings
.MIDDLEWARE_CLASSES
= (
106 'django.contrib.sessions.middleware.SessionMiddleware',
107 'django.contrib.auth.middleware.AuthenticationMiddleware',
108 'django.middleware.common.CommonMiddleware',
112 # Load all the ALWAYS_INSTALLED_APPS.
113 # (This import statement is intentionally delayed until after we
114 # access settings because of the USE_I18N dependency.)
115 from django
.db
.models
.loading
import get_apps
, load_app
118 # Load all the test model apps.
120 for model_dir
, model_name
in get_test_models():
121 model_label
= '.'.join([model_dir
, model_name
])
123 # if the model was named on the command line, or
124 # no models were named (i.e., run all), import
125 # this model and add it to the list to test.
126 if not test_labels
or model_name
in set([label
.split('.')[0] for label
in test_labels
]):
128 print "Importing model %s" % model_name
129 mod
= load_app(model_label
)
131 if model_label
not in settings
.INSTALLED_APPS
:
132 settings
.INSTALLED_APPS
.append(model_label
)
134 sys
.stderr
.write("Error while importing %s:" % model_name
+ ''.join(traceback
.format_exception(*sys
.exc_info())[1:]))
137 # Add tests for invalid models.
139 for model_dir
, model_name
in get_invalid_models():
140 model_label
= '.'.join([model_dir
, model_name
])
141 if not test_labels
or model_name
in test_labels
:
142 extra_tests
.append(InvalidModelTestCase(model_label
))
144 # Run the test suite, including the extra validation tests.
145 from django
.test
.simple
import run_tests
146 failures
= run_tests(test_labels
, verbosity
=verbosity
, interactive
=interactive
, extra_tests
=extra_tests
)
150 # Restore the old settings.
151 settings
.INSTALLED_APPS
= old_installed_apps
152 settings
.ROOT_URLCONF
= old_root_urlconf
153 settings
.TEMPLATE_DIRS
= old_template_dirs
154 settings
.USE_I18N
= old_use_i18n
155 settings
.LANGUAGE_CODE
= old_language_code
156 settings
.MIDDLEWARE_CLASSES
= old_middleware_classes
158 if __name__
== "__main__":
159 from optparse
import OptionParser
160 usage
= "%prog [options] [model model model ...]"
161 parser
= OptionParser(usage
=usage
)
162 parser
.add_option('-v','--verbosity', action
='store', dest
='verbosity', default
='0',
163 type='choice', choices
=['0', '1', '2'],
164 help='Verbosity level; 0=minimal output, 1=normal output, 2=all output')
165 parser
.add_option('--noinput', action
='store_false', dest
='interactive', default
=True,
166 help='Tells Django to NOT prompt the user for input of any kind.')
167 parser
.add_option('--settings',
168 help='Python path to settings module, e.g. "myproject.settings". If this isn\'t provided, the DJANGO_SETTINGS_MODULE environment variable will be used.')
169 options
, args
= parser
.parse_args()
171 os
.environ
['DJANGO_SETTINGS_MODULE'] = options
.settings
172 elif "DJANGO_SETTINGS_MODULE" not in os
.environ
:
173 parser
.error("DJANGO_SETTINGS_MODULE is not set in the environment. "
174 "Set it or use --settings.")
175 django_tests(int(options
.verbosity
), options
.interactive
, args
)