Fixed #3771 -- Modified the test runner to observe the --noinput argument controlling script interactivity. This means that test scripts can now be put in a buildbot environment. This is a backwards incompatible change for anyone that has written a custom test runner. Thanks for the suggestion, moof@metamoof.net.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@5752 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Russell Keith-Magee 2007-07-23 12:14:32 +00:00
parent 304381616f
commit 1b7fe09660
4 changed files with 24 additions and 11 deletions

View File

@ -1331,7 +1331,7 @@ def runfcgi(args):
runfastcgi(args) runfastcgi(args)
runfcgi.args = '[various KEY=val options, use `runfcgi help` for help]' runfcgi.args = '[various KEY=val options, use `runfcgi help` for help]'
def test(app_labels, verbosity=1): def test(app_labels, verbosity=1, interactive=True):
"Runs the test suite for the specified applications" "Runs the test suite for the specified applications"
from django.conf import settings from django.conf import settings
from django.db.models import get_app, get_apps from django.db.models import get_app, get_apps
@ -1350,12 +1350,12 @@ def test(app_labels, verbosity=1):
test_module = __import__(test_module_name, {}, {}, test_path[-1]) test_module = __import__(test_module_name, {}, {}, test_path[-1])
test_runner = getattr(test_module, test_path[-1]) test_runner = getattr(test_module, test_path[-1])
failures = test_runner(app_list, verbosity) failures = test_runner(app_list, verbosity=verbosity, interactive=interactive)
if failures: if failures:
sys.exit(failures) sys.exit(failures)
test.help_doc = 'Runs the test suite for the specified applications, or the entire site if no apps are specified' test.help_doc = 'Runs the test suite for the specified applications, or the entire site if no apps are specified'
test.args = '[--verbosity] ' + APP_ARGS test.args = '[--verbosity] [--noinput]' + APP_ARGS
def load_data(fixture_labels, verbosity=1): def load_data(fixture_labels, verbosity=1):
"Installs the provided fixture file(s) as data in the database." "Installs the provided fixture file(s) as data in the database."
@ -1631,7 +1631,12 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
action_mapping[action](args[1]) action_mapping[action](args[1])
except IndexError: except IndexError:
parser.print_usage_and_exit() parser.print_usage_and_exit()
elif action in ('test', 'loaddata'): elif action == 'test':
try:
action_mapping[action](args[1:], int(options.verbosity), options.interactive)
except IndexError:
parser.print_usage_and_exit()
elif action == 'loaddata':
try: try:
action_mapping[action](args[1:], int(options.verbosity)) action_mapping[action](args[1:], int(options.verbosity))
except IndexError: except IndexError:

View File

@ -69,7 +69,7 @@ def build_suite(app_module):
return suite return suite
def run_tests(module_list, verbosity=1, extra_tests=[]): def run_tests(module_list, verbosity=1, interactive=True, extra_tests=[]):
""" """
Run the unit tests for all the modules in the provided list. Run the unit tests for all the modules in the provided list.
This testrunner will search each of the modules in the provided list, This testrunner will search each of the modules in the provided list,
@ -91,7 +91,7 @@ def run_tests(module_list, verbosity=1, extra_tests=[]):
suite.addTest(test) suite.addTest(test)
old_name = settings.DATABASE_NAME old_name = settings.DATABASE_NAME
create_test_db(verbosity) create_test_db(verbosity, autoclobber=not interactive)
result = unittest.TextTestRunner(verbosity=verbosity).run(suite) result = unittest.TextTestRunner(verbosity=verbosity).run(suite)
destroy_test_db(old_name, verbosity) destroy_test_db(old_name, verbosity)

View File

@ -662,10 +662,10 @@ framework that can be executed from Python code.
Defining a test runner Defining a test runner
---------------------- ----------------------
By convention, a test runner should be called ``run_tests``; however, you By convention, a test runner should be called ``run_tests``; however, you
can call it anything you want. The only requirement is that it accept two can call it anything you want. The only requirement is that it accept three
arguments: arguments:
``run_tests(module_list, verbosity=1)`` ``run_tests(module_list, verbosity=1, interactive=True)``
The module list is the list of Python modules that contain the models to be The module list is the list of Python modules that contain the models to be
tested. This is the same format returned by ``django.db.models.get_apps()`` tested. This is the same format returned by ``django.db.models.get_apps()``
@ -673,6 +673,12 @@ arguments:
will be printed to the console; ``0`` is no output, ``1`` is normal output, will be printed to the console; ``0`` is no output, ``1`` is normal output,
and ``2`` is verbose output. and ``2`` is verbose output.
**New in Django development version** If ``interactive`` is ``True``, the
test suite may ask the user for instructions when the test suite is
executed. An example of this behavior would be asking for permission to
delete an existing test database. If ``interactive`` is ``False, the
test suite must be able to run without any manual intervention.
This method should return the number of tests that failed. This method should return the number of tests that failed.
Testing utilities Testing utilities

View File

@ -73,7 +73,7 @@ class InvalidModelTestCase(unittest.TestCase):
self.assert_(not unexpected, "Unexpected Errors: " + '\n'.join(unexpected)) self.assert_(not unexpected, "Unexpected Errors: " + '\n'.join(unexpected))
self.assert_(not missing, "Missing Errors: " + '\n'.join(missing)) self.assert_(not missing, "Missing Errors: " + '\n'.join(missing))
def django_tests(verbosity, tests_to_run): def django_tests(verbosity, interactive, tests_to_run):
from django.conf import settings from django.conf import settings
old_installed_apps = settings.INSTALLED_APPS old_installed_apps = settings.INSTALLED_APPS
@ -130,7 +130,7 @@ def django_tests(verbosity, tests_to_run):
# Run the test suite, including the extra validation tests. # Run the test suite, including the extra validation tests.
from django.test.simple import run_tests from django.test.simple import run_tests
failures = run_tests(test_models, verbosity, extra_tests=extra_tests) failures = run_tests(test_models, verbosity=verbosity, interactive=interactive, extra_tests=extra_tests)
if failures: if failures:
sys.exit(failures) sys.exit(failures)
@ -149,6 +149,8 @@ if __name__ == "__main__":
parser.add_option('-v','--verbosity', action='store', dest='verbosity', default='0', parser.add_option('-v','--verbosity', action='store', dest='verbosity', default='0',
type='choice', choices=['0', '1', '2'], type='choice', choices=['0', '1', '2'],
help='Verbosity level; 0=minimal output, 1=normal output, 2=all output') help='Verbosity level; 0=minimal output, 1=normal output, 2=all output')
parser.add_option('--noinput', action='store_false', dest='interactive', default=True,
help='Tells Django to NOT prompt the user for input of any kind.')
parser.add_option('--settings', parser.add_option('--settings',
help='Python path to settings module, e.g. "myproject.settings". If this isn\'t provided, the DJANGO_SETTINGS_MODULE environment variable will be used.') help='Python path to settings module, e.g. "myproject.settings". If this isn\'t provided, the DJANGO_SETTINGS_MODULE environment variable will be used.')
options, args = parser.parse_args() options, args = parser.parse_args()
@ -157,4 +159,4 @@ if __name__ == "__main__":
elif "DJANGO_SETTINGS_MODULE" not in os.environ: elif "DJANGO_SETTINGS_MODULE" not in os.environ:
parser.error("DJANGO_SETTINGS_MODULE is not set in the environment. " parser.error("DJANGO_SETTINGS_MODULE is not set in the environment. "
"Set it or use --settings.") "Set it or use --settings.")
django_tests(int(options.verbosity), args) django_tests(int(options.verbosity), options.interactive, args)