2005-07-29 17:15:40 +02:00
#!/usr/bin/env python
2006-08-27 15:59:47 +02:00
import os , sys , traceback
import unittest
2005-07-29 17:15:40 +02:00
2007-05-20 05:51:21 +02:00
import django . contrib as contrib
2007-09-14 11:55:17 +02:00
try :
set
except NameError :
from sets import Set as set # For Python 2.3
2007-05-20 05:51:21 +02:00
CONTRIB_DIR_NAME = ' django.contrib '
2006-05-02 03:31:56 +02:00
MODEL_TESTS_DIR_NAME = ' modeltests '
2006-06-20 07:29:19 +02:00
REGRESSION_TESTS_DIR_NAME = ' regressiontests '
2007-05-20 05:51:21 +02:00
2006-09-02 11:34:40 +02:00
TEST_TEMPLATE_DIR = ' templates '
2005-07-29 17:15:40 +02:00
2007-05-20 05:51:21 +02:00
CONTRIB_DIR = os . path . dirname ( contrib . __file__ )
2006-05-02 03:31:56 +02:00
MODEL_TEST_DIR = os . path . join ( os . path . dirname ( __file__ ) , MODEL_TESTS_DIR_NAME )
2006-06-20 07:29:19 +02:00
REGRESSION_TEST_DIR = os . path . join ( os . path . dirname ( __file__ ) , REGRESSION_TESTS_DIR_NAME )
2005-07-30 00:35:54 +02:00
2006-05-26 23:28:12 +02:00
ALWAYS_INSTALLED_APPS = [
' django.contrib.contenttypes ' ,
2006-06-20 16:27:44 +02:00
' django.contrib.auth ' ,
2007-08-15 13:25:22 +02:00
' django.contrib.sites ' ,
2006-05-26 23:28:12 +02:00
' django.contrib.flatpages ' ,
' django.contrib.redirects ' ,
' django.contrib.sessions ' ,
2006-06-16 20:58:45 +02:00
' django.contrib.comments ' ,
' django.contrib.admin ' ,
2006-05-26 23:28:12 +02:00
]
2005-07-30 00:35:54 +02:00
def get_test_models ( ) :
2006-06-20 09:12:45 +02:00
models = [ ]
2007-05-20 05:51:21 +02:00
for loc , dirpath in ( MODEL_TESTS_DIR_NAME , MODEL_TEST_DIR ) , ( REGRESSION_TESTS_DIR_NAME , REGRESSION_TEST_DIR ) , ( CONTRIB_DIR_NAME , CONTRIB_DIR ) :
2006-06-20 16:27:44 +02:00
for f in os . listdir ( dirpath ) :
2006-08-27 15:59:47 +02:00
if f . startswith ( ' __init__ ' ) or f . startswith ( ' . ' ) or f . startswith ( ' sql ' ) or f . startswith ( ' invalid ' ) :
2006-06-20 09:12:45 +02:00
continue
models . append ( ( loc , f ) )
return models
2005-07-30 00:35:54 +02:00
2006-08-27 15:59:47 +02:00
def get_invalid_models ( ) :
models = [ ]
2007-05-20 05:51:21 +02:00
for loc , dirpath in ( MODEL_TESTS_DIR_NAME , MODEL_TEST_DIR ) , ( REGRESSION_TESTS_DIR_NAME , REGRESSION_TEST_DIR ) , ( CONTRIB_DIR_NAME , CONTRIB_DIR ) :
2006-08-27 15:59:47 +02:00
for f in os . listdir ( dirpath ) :
if f . startswith ( ' __init__ ' ) or f . startswith ( ' . ' ) or f . startswith ( ' sql ' ) :
continue
if f . startswith ( ' invalid ' ) :
models . append ( ( loc , f ) )
return models
2006-12-15 07:06:52 +01:00
2006-08-27 15:59:47 +02:00
class InvalidModelTestCase ( unittest . TestCase ) :
def __init__ ( self , model_label ) :
unittest . TestCase . __init__ ( self )
self . model_label = model_label
2006-12-15 07:06:52 +01:00
2006-08-27 15:59:47 +02:00
def runTest ( self ) :
2007-08-16 08:06:55 +02:00
from django . core . management . validation import get_validation_errors
2006-06-23 06:37:00 +02:00
from django . db . models . loading import load_app
2006-08-27 15:59:47 +02:00
from cStringIO import StringIO
try :
module = load_app ( self . model_label )
except Exception , e :
self . fail ( ' Unable to load invalid model module ' )
2006-12-15 07:06:52 +01:00
2007-08-17 14:29:08 +02:00
# Make sure sys.stdout is not a tty so that we get errors without
# coloring attached (makes matching the results easier). We restore
# sys.stderr afterwards.
orig_stdout = sys . stdout
2006-08-27 15:59:47 +02:00
s = StringIO ( )
2007-08-17 14:29:08 +02:00
sys . stdout = s
2007-08-16 08:06:55 +02:00
count = get_validation_errors ( s , module )
2007-08-17 14:29:08 +02:00
sys . stdout = orig_stdout
2006-08-27 15:59:47 +02:00
s . seek ( 0 )
error_log = s . read ( )
actual = error_log . split ( ' \n ' )
expected = module . model_errors . split ( ' \n ' )
unexpected = [ err for err in actual if err not in expected ]
missing = [ err for err in expected if err not in actual ]
self . assert_ ( not unexpected , " Unexpected Errors: " + ' \n ' . join ( unexpected ) )
self . assert_ ( not missing , " Missing Errors: " + ' \n ' . join ( missing ) )
2007-07-28 06:02:52 +02:00
def django_tests ( verbosity , interactive , test_labels ) :
2006-08-27 15:59:47 +02:00
from django . conf import settings
2006-09-02 11:34:40 +02:00
2006-08-27 15:59:47 +02:00
old_installed_apps = settings . INSTALLED_APPS
2006-09-01 15:33:26 +02:00
old_test_database_name = settings . TEST_DATABASE_NAME
2008-08-30 07:09:03 +02:00
old_root_urlconf = getattr ( settings , " ROOT_URLCONF " , " " )
2006-09-02 11:34:40 +02:00
old_template_dirs = settings . TEMPLATE_DIRS
2006-12-15 07:06:52 +01:00
old_use_i18n = settings . USE_I18N
2007-12-17 11:31:20 +01:00
old_login_url = settings . LOGIN_URL
2007-10-21 19:26:32 +02:00
old_language_code = settings . LANGUAGE_CODE
2007-02-10 05:01:19 +01:00
old_middleware_classes = settings . MIDDLEWARE_CLASSES
2006-12-15 07:06:52 +01:00
2007-02-10 05:01:19 +01:00
# Redirect some settings for the duration of these tests.
2006-08-27 15:59:47 +02:00
settings . INSTALLED_APPS = ALWAYS_INSTALLED_APPS
2006-09-02 11:34:40 +02:00
settings . ROOT_URLCONF = ' urls '
settings . TEMPLATE_DIRS = ( os . path . join ( os . path . dirname ( __file__ ) , TEST_TEMPLATE_DIR ) , )
2006-12-15 07:06:52 +01:00
settings . USE_I18N = True
2007-10-21 19:26:32 +02:00
settings . LANGUAGE_CODE = ' en '
2007-12-17 11:31:20 +01:00
settings . LOGIN_URL = ' /accounts/login/ '
2007-02-10 05:01:19 +01:00
settings . MIDDLEWARE_CLASSES = (
' django.contrib.sessions.middleware.SessionMiddleware ' ,
' django.contrib.auth.middleware.AuthenticationMiddleware ' ,
' django.middleware.common.CommonMiddleware ' ,
)
2007-12-01 22:58:51 +01:00
settings . SITE_ID = 1
2009-03-23 22:07:02 +01:00
# For testing comment-utils, we require the MANAGERS attribute
# to be set, so that a test email is sent out which we catch
# in our tests.
settings . MANAGERS = ( " admin@djangoproject.com " , )
2006-12-15 07:06:52 +01:00
# Load all the ALWAYS_INSTALLED_APPS.
# (This import statement is intentionally delayed until after we
# access settings because of the USE_I18N dependency.)
from django . db . models . loading import get_apps , load_app
2006-08-27 15:59:47 +02:00
get_apps ( )
2006-12-15 07:06:52 +01:00
2007-02-10 05:01:19 +01:00
# Load all the test model apps.
2006-12-15 07:06:52 +01:00
for model_dir , model_name in get_test_models ( ) :
2006-08-27 15:59:47 +02:00
model_label = ' . ' . join ( [ model_dir , model_name ] )
try :
# if the model was named on the command line, or
2006-12-15 07:06:52 +01:00
# no models were named (i.e., run all), import
2006-08-27 15:59:47 +02:00
# this model and add it to the list to test.
2007-07-28 06:02:52 +02:00
if not test_labels or model_name in set ( [ label . split ( ' . ' ) [ 0 ] for label in test_labels ] ) :
2006-08-27 15:59:47 +02:00
if verbosity > = 1 :
print " Importing model %s " % model_name
mod = load_app ( model_label )
2007-05-20 05:51:21 +02:00
if mod :
if model_label not in settings . INSTALLED_APPS :
settings . INSTALLED_APPS . append ( model_label )
2006-08-27 15:59:47 +02:00
except Exception , e :
sys . stderr . write ( " Error while importing %s : " % model_name + ' ' . join ( traceback . format_exception ( * sys . exc_info ( ) ) [ 1 : ] ) )
2006-12-15 07:06:52 +01:00
continue
2006-08-27 15:59:47 +02:00
2007-02-10 05:01:19 +01:00
# Add tests for invalid models.
2006-08-27 15:59:47 +02:00
extra_tests = [ ]
for model_dir , model_name in get_invalid_models ( ) :
model_label = ' . ' . join ( [ model_dir , model_name ] )
2007-07-28 06:02:52 +02:00
if not test_labels or model_name in test_labels :
2006-08-27 15:59:47 +02:00
extra_tests . append ( InvalidModelTestCase ( model_label ) )
2008-06-06 14:55:38 +02:00
try :
2008-10-02 14:57:13 +02:00
# Invalid models are not working apps, so we cannot pass them into
2008-06-06 14:55:38 +02:00
# the test runner with the other test_labels
test_labels . remove ( model_name )
except ValueError :
pass
2008-10-02 14:57:13 +02:00
2006-08-27 15:59:47 +02:00
# Run the test suite, including the extra validation tests.
2009-02-28 05:46:38 +01:00
from django . test . utils import get_runner
if not hasattr ( settings , ' TEST_RUNNER ' ) :
settings . TEST_RUNNER = ' django.test.simple.run_tests '
test_runner = get_runner ( settings )
failures = test_runner ( test_labels , verbosity = verbosity , interactive = interactive , extra_tests = extra_tests )
2007-02-26 13:52:01 +01:00
if failures :
sys . exit ( failures )
2006-12-15 07:06:52 +01:00
2007-02-10 05:01:19 +01:00
# Restore the old settings.
2006-08-27 15:59:47 +02:00
settings . INSTALLED_APPS = old_installed_apps
2006-09-02 11:34:40 +02:00
settings . ROOT_URLCONF = old_root_urlconf
settings . TEMPLATE_DIRS = old_template_dirs
2006-12-15 07:06:52 +01:00
settings . USE_I18N = old_use_i18n
2007-10-21 19:26:32 +02:00
settings . LANGUAGE_CODE = old_language_code
2007-12-17 11:31:20 +01:00
settings . LOGIN_URL = old_login_url
2007-02-10 05:01:19 +01:00
settings . MIDDLEWARE_CLASSES = old_middleware_classes
2006-12-15 07:06:52 +01:00
2005-07-29 17:15:40 +02:00
if __name__ == " __main__ " :
from optparse import OptionParser
2005-09-19 03:18:04 +02:00
usage = " % prog [options] [model model model ...] "
2006-02-18 21:08:20 +01:00
parser = OptionParser ( usage = usage )
2006-08-27 15:59:47 +02:00
parser . add_option ( ' -v ' , ' --verbosity ' , action = ' store ' , dest = ' verbosity ' , default = ' 0 ' ,
type = ' choice ' , choices = [ ' 0 ' , ' 1 ' , ' 2 ' ] ,
2006-12-15 07:06:52 +01:00
help = ' Verbosity level; 0=minimal output, 1=normal output, 2=all output ' )
2007-07-23 14:14:32 +02:00
parser . add_option ( ' --noinput ' , action = ' store_false ' , dest = ' interactive ' , default = True ,
help = ' Tells Django to NOT prompt the user for input of any kind. ' )
2005-08-10 17:36:16 +02:00
parser . add_option ( ' --settings ' ,
2006-01-01 19:37:33 +01:00
help = ' Python path to settings module, e.g. " myproject.settings " . If this isn \' t provided, the DJANGO_SETTINGS_MODULE environment variable will be used. ' )
2005-07-29 17:15:40 +02:00
options , args = parser . parse_args ( )
2005-08-10 17:36:16 +02:00
if options . settings :
os . environ [ ' DJANGO_SETTINGS_MODULE ' ] = options . settings
2007-02-26 23:34:56 +01:00
elif " DJANGO_SETTINGS_MODULE " not in os . environ :
parser . error ( " DJANGO_SETTINGS_MODULE is not set in the environment. "
" Set it or use --settings. " )
2007-07-23 14:14:32 +02:00
django_tests ( int ( options . verbosity ) , options . interactive , args )