diff --git a/django/core/management/commands/test.py b/django/core/management/commands/test.py
index 1b3f2be..17fdba0 100644
--- a/django/core/management/commands/test.py
+++ b/django/core/management/commands/test.py
@@ -12,7 +12,9 @@ class Command(BaseCommand):
             help='Tells Django to stop running the test suite after first failed test.'),
         make_option('--testrunner', action='store', dest='testrunner',
             help='Tells Django to use specified test runner class instead of the one '+
-                 'specified by the TEST_RUNNER setting.')
+                 'specified by the TEST_RUNNER setting.'),
+        make_option('-e', '--exclude', dest='exclude_labels', action='append', default=[],
+            help='Test to exclude (use multiple --exclude to exclude multiple tests).'),
     )
     help = 'Runs the test suite for the specified applications, or the entire site if no apps are specified.'
     args = '[appname ...]'
@@ -51,7 +53,9 @@ class Command(BaseCommand):
         options.setdefault('failfast', False)
 
         test_runner = TestRunner(**options)
-        failures = test_runner.run_tests(test_labels)
+        exclude_labels = options.get('exclude_labels')
+        failures = test_runner.run_tests(test_labels,
+                                         exclude_labels=exclude_labels)
 
         if failures:
             sys.exit(bool(failures))
diff --git a/django/test/simple.py b/django/test/simple.py
index c9adfd2..d345d2e 100644
--- a/django/test/simple.py
+++ b/django/test/simple.py
@@ -7,6 +7,7 @@ from django.test import _doctest as doctest
 from django.test.utils import setup_test_environment, teardown_test_environment
 from django.test.testcases import OutputChecker, DocTestRunner, TestCase
 from django.utils import unittest
+from django.utils.datastructures import SortedDict
 from django.utils.importlib import import_module
 from django.utils.module_loading import module_has_submodule
 
@@ -50,103 +51,134 @@ def get_tests(app_module):
     return test_module
 
 def build_suite(app_module):
-    "Create a complete Django test suite for the provided application module"
+    """
+    Create a complete Django test suite for the provided application module
+    """
     suite = unittest.TestSuite()
 
-    # Load unit and doctests in the models.py module. If module has
-    # a suite() method, use it. Otherwise build the test suite ourselves.
-    if hasattr(app_module, 'suite'):
-        suite.addTest(app_module.suite())
-    else:
-        suite.addTest(unittest.defaultTestLoader.loadTestsFromModule(app_module))
-        try:
-            suite.addTest(doctest.DocTestSuite(app_module,
-                                               checker=doctestOutputChecker,
-                                               runner=DocTestRunner))
-        except ValueError:
-            # No doc tests in models.py
-            pass
-
-    # Check to see if a separate 'tests' module exists parallel to the
-    # models 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'):
-            suite.addTest(test_module.suite())
-        else:
-            suite.addTest(unittest.defaultTestLoader.loadTestsFromModule(test_module))
-            try:
-                suite.addTest(doctest.DocTestSuite(test_module,
-                                                   checker=doctestOutputChecker,
-                                                   runner=DocTestRunner))
-            except ValueError:
-                # No doc tests in tests.py
-                pass
+
+    for module in (app_module, test_module):
+        if module:
+            # Load unit and doctests in the module. If the module has a
+            # suite() method, use it. Otherwise build the test suite ourselves.
+            if hasattr(module, 'suite'):
+                suite.addTest(module.suite())
+            else:
+                suite.addTest(unittest.defaultTestLoader.loadTestsFromModule(module))
+                try:
+                    suite.addTest(doctest.DocTestSuite(module,
+                                                       checker=doctestOutputChecker,
+                                                       runner=DocTestRunner))
+                except ValueError:
+                    # No doc tests
+                    pass
     return suite
 
-def build_test(label):
-    """Construct a test case 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.
+def get_test_cases(module, test_label, app_label, TestClass=None, test_name=None):
+    test_cases = SortedDict()
+    if TestClass is None:
+        for test_name in dir(module):
+            obj = getattr(module, test_name)
+            if isinstance(obj, type) and issubclass(obj, unittest.TestCase):
+                test_cases.update(get_test_cases(test_label, module, app_label, obj))
+    else:
+        try:
+            if issubclass(TestClass, (unittest.TestCase, real_unittest.TestCase)):
+                if test_name: # label is app.TestClass.test_method
+                    label = '%s.%s.%s' % (app_label, TestClass.__name__, test_name)
+                    test_cases[label] = TestClass(test_name)
+                else: # label is app.TestClass
+                    try:
+                        for test_name in unittest.TestLoader().getTestCaseNames(TestClass):
+                            label = '%s.%s.%s' % (app_label, TestClass.__name__, test_name)
+                            test_cases[label] = TestClass(test_name)
+                    except TypeError:
+                        raise ValueError("Test label '%s' does not refer to a test class" % test_label)
+        except TypeError:
+            # TestClass isn't a TestClass - it must be a method or normal class
+            print "aa"
+    return test_cases
+
+def get_doctests(module, test_label):
+    parts = test_label.split('.')
+    doctests = SortedDict()
+    try:
+        existing_doctests = doctest.DocTestSuite(module,
+                                        checker=doctestOutputChecker,
+                                        runner=DocTestRunner)
+        # Now iterate over the suite, looking for doctests whose name
+        # matches the pattern that was given
+        for test in existing_doctests:
+            if test._dt_test.name in (
+                    '%s.%s' % (module.__name__, '.'.join(parts[1:])),
+                    '%s.__test__.%s' % (module.__name__, '.'.join(parts[1:]))):
+                doctests[test._dt_test.name] = test
+    except ValueError:
+        # No doctests found.
+        pass
+    return doctests
 
+def get_test_dict(label):
+    """
+    Returns a SortedDict with the associations label->test, where label is a
+    full string reference to a test (of the form app.TestClass.test_method) and
+    test is either a test case or a doctest. For example:
+
+        {
+            'auth.AnonymousUserBackendTest.test_get_all_permissions':
+                <django.contrib.auth.tests.auth_backends.AnonymousUserBackendTest testMethod=test_get_all_permissions>,
+            'auth.AnonymousUserBackendTest.test_has_module_perms':
+                <django.contrib.auth.tests.auth_backends.AnonymousUserBackendTest testMethod=test_has_module_perms>,
+            ...
+        }
     """
     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)
 
-    #
-    # First, look for TestCase instances with a name that matches
-    #
-    app_module = get_app(parts[0])
-    test_module = get_tests(app_module)
-    TestClass = getattr(app_module, parts[1], None)
+    if len(parts) < 1 or len(parts) > 3:
+        raise ValueError("Test label '%s' should be of the form app, app.TestCase or app.TestCase.test_method" % label)
 
-    # Couldn't find the test class in models.py; look in tests.py
-    if TestClass is None:
-        if test_module:
-            TestClass = getattr(test_module, parts[1], None)
+    # First, parse the label to figure out the app, the TestCase and the test_method.
+    app_label = parts[0]
+    app_module = get_app(app_label)
+    test_module = get_tests(app_module)
 
-    try:
-        if issubclass(TestClass, (unittest.TestCase, real_unittest.TestCase)):
-            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])
-    except TypeError:
-        # TestClass isn't a TestClass - it must be a method or normal class
-        pass
+    if len(parts) == 1:
+        # Test label of the form: app
+        TestClass = None
+        test_name = None
+    else:
+        TestClass = getattr(app_module, parts[1], None)
+        # Couldn't find the test class in models.py; look in tests.py
+        if TestClass is None:
+            if test_module:
+                TestClass = getattr(test_module, parts[1], None)
+
+        if len(parts) == 2:
+            # Test label of the form: app.TestCase
+            test_name = None
+        else:
+            # Test label of the form: app.TestCase.test_method
+            test_name = parts[2]
+
+    # Then, generate the SortedDict of tests.
+    test_dict = SortedDict()
+    for module in (app_module, test_module):
+        if hasattr(module, 'suite'):
+            # If the module defines a suite() method then use it instead.
+            test_dict.update({
+                '%s.%s' % (app_label, module.__name__): module.suite()
+            })
+            # TODO: introspect the custom suite to unfold the whole test names.
+        else:
+            # Get the module's test cases
+            test_cases = get_test_cases(module, label, app_label, TestClass, test_name)
+            test_dict.update(test_cases)
+            # Get the module's doctests
+            doctests = get_doctests(module, label)
+            test_dict.update(doctests)
+    return test_dict
 
-    #
-    # If there isn't a TestCase, look for a doctest that matches
-    #
-    tests = []
-    for module in app_module, test_module:
-        try:
-            doctests = doctest.DocTestSuite(module,
-                                            checker=doctestOutputChecker,
-                                            runner=DocTestRunner)
-            # Now iterate over the suite, looking for doctests whose name
-            # matches the pattern that was given
-            for test in doctests:
-                if test._dt_test.name in (
-                        '%s.%s' % (module.__name__, '.'.join(parts[1:])),
-                        '%s.__test__.%s' % (module.__name__, '.'.join(parts[1:]))):
-                    tests.append(test)
-        except ValueError:
-            # No doctests found.
-            pass
-
-    # If no tests were found, then we were given a bad test label.
-    if not tests:
-        raise ValueError("Test label '%s' does not refer to a test" % label)
-
-    # Construct a suite out of the tests that matched.
-    return unittest.TestSuite(tests)
 
 def partition_suite(suite, classes, bins):
     """
@@ -234,16 +266,32 @@ class DjangoTestSuiteRunner(object):
     def build_suite(self, test_labels, extra_tests=None, **kwargs):
         suite = unittest.TestSuite()
 
-        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))
+        if not test_labels:
+            test_labels = []
+            for app_label in settings.INSTALLED_APPS:
+                test_labels.append(app_label.split('.')[-1])
+
+        test_dict = SortedDict()
+        for label in test_labels:
+            test_dict.update(get_test_dict(label))
+
+        excluded_dict = SortedDict()
+        for label in kwargs.get('exclude_labels'):
+            excluded_dict.update(get_test_dict(label))
+
+        for label, test in excluded_dict.iteritems():
+            try:
+                # Remove from the dictionary of executable tests
+                del test_dict[label]
+            except KeyError:
+                # It's OK if we're trying to exclude a test label that isn't
+                # part of the original suite. Simply ignore.
+                pass
+            if self.verbosity >= 1:
+                print 'Excluding test: %s' % label
+
+        for label, test in test_dict.iteritems():
+            suite.addTest(test)
 
         if extra_tests:
             for test in extra_tests:
@@ -347,10 +395,14 @@ class DjangoTestSuiteRunner(object):
         A list of 'extra' tests may also be provided; these tests
         will be added to the test suite.
 
+        It's also possible to specify a list of labels to exclude from the
+        test suite by using the exclude_labels parameter.
+
         Returns the number of tests that failed.
         """
+        exclude_labels = kwargs.get('exclude_labels')
         self.setup_test_environment()
-        suite = self.build_suite(test_labels, extra_tests)
+        suite = self.build_suite(test_labels, extra_tests, exclude_labels=exclude_labels)
         old_config = self.setup_databases()
         result = self.run_suite(suite)
         self.teardown_databases(old_config)
diff --git a/tests/runtests.py b/tests/runtests.py
index ba66d2a..264b1d7 100755
--- a/tests/runtests.py
+++ b/tests/runtests.py
@@ -79,7 +79,7 @@ class InvalidModelTestCase(unittest.TestCase):
 
         try:
             module = load_app(self.module_label)
-        except Exception, e:
+        except Exception:
             self.fail('Unable to load invalid model module')
 
         # Make sure sys.stdout is not a tty so that we get errors without
@@ -88,7 +88,7 @@ class InvalidModelTestCase(unittest.TestCase):
         orig_stdout = sys.stdout
         s = StringIO()
         sys.stdout = s
-        count = get_validation_errors(s, module)
+        get_validation_errors(s, module)
         sys.stdout = orig_stdout
         s.seek(0)
         error_log = s.read()
@@ -101,7 +101,7 @@ class InvalidModelTestCase(unittest.TestCase):
         self.assertTrue(not unexpected, "Unexpected Errors: " + '\n'.join(unexpected))
         self.assertTrue(not missing, "Missing Errors: " + '\n'.join(missing))
 
-def setup(verbosity, test_labels):
+def setup(verbosity, test_labels, exclude_labels):
     from django.conf import settings
     state = {
         'INSTALLED_APPS': settings.INSTALLED_APPS,
@@ -136,15 +136,22 @@ def setup(verbosity, test_labels):
     # in our tests.
     settings.MANAGERS = ("admin@djangoproject.com",)
 
+    if exclude_labels is None:
+        exclude_labels = []
+
     # 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
     get_apps()
 
+    # Only avoid loading an app if it is fully excluded, if testscases or test
+    # methods names were excluded then load its apps normally.
+    exclude_apps = [label for label in exclude_labels if '.' not in label]
+
     # Load all the test model apps.
-    test_labels_set = set([label.split('.')[0] for label in test_labels])
     test_modules = get_test_modules()
+    test_labels_set = set([label.split('.')[0] for label in test_labels if label not in exclude_apps])
 
     # If GeoDjango, then we'll want to add in the test applications
     # that are a part of its test suite.
@@ -154,10 +161,14 @@ def setup(verbosity, test_labels):
 
     for module_dir, module_name in test_modules:
         module_label = '.'.join([module_dir, module_name])
-        # if the module was named on the command line, or
-        # no modules were named (i.e., run all), import
-        # this module and add it to the list to test.
+        # if the model was named on the command line, or no models were named
+        # (i.e., run all), import this model and add it to the list to test.
+        # Also, skip importing the test apps explicitly excluded by the user.
         if not test_labels or module_name in test_labels_set:
+            if module_name in exclude_apps:
+                if verbosity >= 2:
+                    print "Skipping import of app %s" % module_name
+                    continue
             if verbosity >= 2:
                 print "Importing application %s" % module_name
             mod = load_app(module_label)
@@ -175,9 +186,9 @@ def teardown(state):
     for key, value in state.items():
         setattr(settings, key, value)
 
-def django_tests(verbosity, interactive, failfast, test_labels):
+def django_tests(verbosity, interactive, failfast, test_labels, exclude_labels=None):
     from django.conf import settings
-    state = setup(verbosity, test_labels)
+    state = setup(verbosity, test_labels, exclude_labels)
 
     # Add tests for invalid models apps.
     extra_tests = []
@@ -198,14 +209,15 @@ def django_tests(verbosity, interactive, failfast, test_labels):
         from django.contrib.gis.tests import geodjango_suite
         extra_tests.append(geodjango_suite(apps=False))
 
-    # Run the test suite, including the extra validation tests.
+    # Run the test suite, including the extra validation tests and skipping
+    # the test explicitely excluded.
     from django.test.utils import get_runner
     if not hasattr(settings, 'TEST_RUNNER'):
         settings.TEST_RUNNER = 'django.test.simple.DjangoTestSuiteRunner'
     TestRunner = get_runner(settings)
 
     test_runner = TestRunner(verbosity=verbosity, interactive=interactive, failfast=failfast)
-    failures = test_runner.run_tests(test_labels, extra_tests=extra_tests)
+    failures = test_runner.run_tests(test_labels, extra_tests=extra_tests, exclude_labels=exclude_labels)
 
     teardown(state)
     return failures
@@ -324,6 +336,8 @@ if __name__ == "__main__":
         help="Bisect the test suite to discover a test that causes a test failure when combined with the named test.")
     parser.add_option('--pair', action='store', dest='pair', default=None,
         help="Run the test suite in pairs with the named test to find problem pairs.")
+    parser.add_option('-e', '--exclude', action='append', dest='exclude', default=[],
+        help='Test to exclude (use multiple --exclude to exclude multiple tests).')
     options, args = parser.parse_args()
     if options.settings:
         os.environ['DJANGO_SETTINGS_MODULE'] = options.settings
@@ -338,6 +352,12 @@ if __name__ == "__main__":
     elif options.pair:
         paired_tests(options.pair, options, args)
     else:
-        failures = django_tests(int(options.verbosity), options.interactive, options.failfast, args)
+        failures = django_tests(
+                int(options.verbosity),
+                options.interactive,
+                options.failfast,
+                args,
+                options.exclude
+            )
         if failures:
             sys.exit(bool(failures))
