app/django/test/simple.py
changeset 54 03e267d67478
child 323 ff1a9aa48cfd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/django/test/simple.py	Fri Jul 18 18:22:23 2008 +0000
@@ -0,0 +1,148 @@
+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
+from django.test.testcases import OutputChecker, DocTestRunner
+
+# The module name for tests outside models.py
+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()
+    
+    # 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
+    return suite
+
+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 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.
+    """
+    setup_test_environment()
+    
+    settings.DEBUG = False    
+    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))
+    
+    for test in extra_tests:
+        suite.addTest(test)
+
+    old_name = settings.DATABASE_NAME
+    create_test_db(verbosity, autoclobber=not interactive)
+    result = unittest.TextTestRunner(verbosity=verbosity).run(suite)
+    destroy_test_db(old_name, verbosity)
+    
+    teardown_test_environment()
+    
+    return len(result.failures) + len(result.errors)