summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorRussell Keith-Magee <russell@keith-magee.com>2007-07-28 04:02:52 +0000
committerRussell Keith-Magee <russell@keith-magee.com>2007-07-28 04:02:52 +0000
commit650cea9170313d9a2197d4050f6dcabaaeaa3b20 (patch)
tree971b87274c3a17d6e8df842ecf48a98d594602e1 /django
parent5b8d2c9f0df1dbfadafeea6420fc5fc175e00376 (diff)
Fixed #4460 -- Added the ability to be more specific in the test cases that are executed. This is a backwards incompatible change for any user with a custom test runner. See the wiki for details.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@5769 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django')
-rw-r--r--django/core/management.py11
-rw-r--r--django/test/simple.py112
2 files changed, 83 insertions, 40 deletions
diff --git a/django/core/management.py b/django/core/management.py
index 4862a7833f..edf11ce478 100644
--- a/django/core/management.py
+++ b/django/core/management.py
@@ -1331,16 +1331,11 @@ def runfcgi(args):
runfastcgi(args)
runfcgi.args = '[various KEY=val options, use `runfcgi help` for help]'
-def test(app_labels, verbosity=1, interactive=True):
+def test(test_labels, verbosity=1, interactive=True):
"Runs the test suite for the specified applications"
from django.conf import settings
from django.db.models import get_app, get_apps
-
- if len(app_labels) == 0:
- app_list = get_apps()
- else:
- app_list = [get_app(app_label) for app_label in app_labels]
-
+
test_path = settings.TEST_RUNNER.split('.')
# Allow for Python 2.5 relative paths
if len(test_path) > 1:
@@ -1350,7 +1345,7 @@ def test(app_labels, verbosity=1, interactive=True):
test_module = __import__(test_module_name, {}, {}, test_path[-1])
test_runner = getattr(test_module, test_path[-1])
- failures = test_runner(app_list, verbosity=verbosity, interactive=interactive)
+ failures = test_runner(test_labels, verbosity=verbosity, interactive=interactive)
if failures:
sys.exit(failures)
diff --git a/django/test/simple.py b/django/test/simple.py
index 08e27429e4..6fa381ac4d 100644
--- a/django/test/simple.py
+++ b/django/test/simple.py
@@ -1,5 +1,6 @@
import unittest
from django.conf import settings
+from django.db.models import get_app, get_apps
from django.test import _doctest as doctest
from django.test.utils import setup_test_environment, teardown_test_environment
from django.test.utils import create_test_db, destroy_test_db
@@ -10,6 +11,31 @@ TEST_MODULE = 'tests'
doctestOutputChecker = OutputChecker()
+def get_tests(app_module):
+ try:
+ app_path = app_module.__name__.split('.')[:-1]
+ test_module = __import__('.'.join(app_path + [TEST_MODULE]), {}, {}, TEST_MODULE)
+ except ImportError, e:
+ # Couldn't import tests.py. Was it due to a missing file, or
+ # due to an import error in a tests.py that actually exists?
+ import os.path
+ from imp import find_module
+ try:
+ mod = find_module(TEST_MODULE, [os.path.dirname(app_module.__file__)])
+ except ImportError:
+ # 'tests' module doesn't exist. Move on.
+ test_module = None
+ else:
+ # The module exists, so there must be an import error in the
+ # test module itself. We don't need the module; so if the
+ # module was a single file module (i.e., tests.py), close the file
+ # handle returned by find_module. Otherwise, the test module
+ # is a directory, and there is nothing to close.
+ if mod[0]:
+ mod[0].close()
+ raise
+ return test_module
+
def build_suite(app_module):
"Create a complete Django test suite for the provided application module"
suite = unittest.TestSuite()
@@ -30,10 +56,8 @@ def build_suite(app_module):
# Check to see if a separate 'tests' module exists parallel to the
# models module
- try:
- app_path = app_module.__name__.split('.')[:-1]
- test_module = __import__('.'.join(app_path + [TEST_MODULE]), {}, {}, TEST_MODULE)
-
+ test_module = get_tests(app_module)
+ if test_module:
# Load unit and doctests in the tests.py module. If module has
# a suite() method, use it. Otherwise build the test suite ourselves.
if hasattr(test_module, 'suite'):
@@ -47,34 +71,50 @@ def build_suite(app_module):
except ValueError:
# No doc tests in tests.py
pass
- except ImportError, e:
- # Couldn't import tests.py. Was it due to a missing file, or
- # due to an import error in a tests.py that actually exists?
- import os.path
- from imp import find_module
- try:
- mod = find_module(TEST_MODULE, [os.path.dirname(app_module.__file__)])
- except ImportError:
- # 'tests' module doesn't exist. Move on.
- pass
- else:
- # The module exists, so there must be an import error in the
- # test module itself. We don't need the module; so if the
- # module was a single file module (i.e., tests.py), close the file
- # handle returned by find_module. Otherwise, the test module
- # is a directory, and there is nothing to close.
- if mod[0]:
- mod[0].close()
- raise
-
return suite
-def run_tests(module_list, verbosity=1, interactive=True, extra_tests=[]):
+def build_test(label):
+ """Construct a test case a test with the specified label. Label should
+ be of the form model.TestClass or model.TestClass.test_method. Returns
+ an instantiated test or test suite corresponding to the label provided.
+
+ """
+ parts = label.split('.')
+ if len(parts) < 2 or len(parts) > 3:
+ raise ValueError("Test label '%s' should be of the form app.TestCase or app.TestCase.test_method" % label)
+
+ app_module = get_app(parts[0])
+ TestClass = getattr(app_module, parts[1], None)
+
+ # Couldn't find the test class in models.py; look in tests.py
+ if TestClass is None:
+ test_module = get_tests(app_module)
+ if test_module:
+ TestClass = getattr(test_module, parts[1], None)
+
+ if len(parts) == 2: # label is app.TestClass
+ try:
+ return unittest.TestLoader().loadTestsFromTestCase(TestClass)
+ except TypeError:
+ raise ValueError("Test label '%s' does not refer to a test class" % label)
+ else: # label is app.TestClass.test_method
+ return TestClass(parts[2])
+
+def run_tests(test_labels, verbosity=1, interactive=True, extra_tests=[]):
"""
- Run the unit tests for all the modules in the provided list.
- This testrunner will search each of the modules in the provided list,
- looking for doctests and unittests in models.py or tests.py within
- the module. A list of 'extra' tests may also be provided; these tests
+ Run the unit tests for all the test labels in the provided list.
+ Labels must be of the form:
+ - app.TestClass.test_method
+ Run a single specific test method
+ - app.TestClass
+ Run all the test methods in a given class
+ - app
+ Search for doctests and unittests in the named application.
+
+ When looking for tests, the test runner will look in the models and
+ tests modules for the application.
+
+ A list of 'extra' tests may also be provided; these tests
will be added to the test suite.
Returns the number of tests that failed.
@@ -83,9 +123,17 @@ def run_tests(module_list, verbosity=1, interactive=True, extra_tests=[]):
settings.DEBUG = False
suite = unittest.TestSuite()
-
- for module in module_list:
- suite.addTest(build_suite(module))
+
+ if test_labels:
+ for label in test_labels:
+ if '.' in label:
+ suite.addTest(build_test(label))
+ else:
+ app = get_app(label)
+ suite.addTest(build_suite(app))
+ else:
+ for app in get_apps():
+ suite.addTest(build_suite(app))
for test in extra_tests:
suite.addTest(test)