app/django/test/simple.py
changeset 54 03e267d67478
child 323 ff1a9aa48cfd
equal deleted inserted replaced
53:57b4279d8c4e 54:03e267d67478
       
     1 import unittest
       
     2 from django.conf import settings
       
     3 from django.db.models import get_app, get_apps
       
     4 from django.test import _doctest as doctest
       
     5 from django.test.utils import setup_test_environment, teardown_test_environment
       
     6 from django.test.utils import create_test_db, destroy_test_db
       
     7 from django.test.testcases import OutputChecker, DocTestRunner
       
     8 
       
     9 # The module name for tests outside models.py
       
    10 TEST_MODULE = 'tests'
       
    11     
       
    12 doctestOutputChecker = OutputChecker()
       
    13 
       
    14 def get_tests(app_module):
       
    15     try:
       
    16         app_path = app_module.__name__.split('.')[:-1]
       
    17         test_module = __import__('.'.join(app_path + [TEST_MODULE]), {}, {}, TEST_MODULE)
       
    18     except ImportError, e:
       
    19         # Couldn't import tests.py. Was it due to a missing file, or
       
    20         # due to an import error in a tests.py that actually exists?
       
    21         import os.path
       
    22         from imp import find_module
       
    23         try:
       
    24             mod = find_module(TEST_MODULE, [os.path.dirname(app_module.__file__)])
       
    25         except ImportError:
       
    26             # 'tests' module doesn't exist. Move on.
       
    27             test_module = None
       
    28         else:
       
    29             # The module exists, so there must be an import error in the 
       
    30             # test module itself. We don't need the module; so if the
       
    31             # module was a single file module (i.e., tests.py), close the file
       
    32             # handle returned by find_module. Otherwise, the test module
       
    33             # is a directory, and there is nothing to close.
       
    34             if mod[0]:
       
    35                 mod[0].close()
       
    36             raise
       
    37     return test_module
       
    38     
       
    39 def build_suite(app_module):
       
    40     "Create a complete Django test suite for the provided application module"
       
    41     suite = unittest.TestSuite()
       
    42     
       
    43     # Load unit and doctests in the models.py module. If module has
       
    44     # a suite() method, use it. Otherwise build the test suite ourselves.
       
    45     if hasattr(app_module, 'suite'):
       
    46         suite.addTest(app_module.suite())
       
    47     else:
       
    48         suite.addTest(unittest.defaultTestLoader.loadTestsFromModule(app_module))
       
    49         try:
       
    50             suite.addTest(doctest.DocTestSuite(app_module,
       
    51                                                checker=doctestOutputChecker,
       
    52                                                runner=DocTestRunner))
       
    53         except ValueError:
       
    54             # No doc tests in models.py
       
    55             pass
       
    56     
       
    57     # Check to see if a separate 'tests' module exists parallel to the 
       
    58     # models module
       
    59     test_module = get_tests(app_module)
       
    60     if test_module:
       
    61         # Load unit and doctests in the tests.py module. If module has
       
    62         # a suite() method, use it. Otherwise build the test suite ourselves.
       
    63         if hasattr(test_module, 'suite'):
       
    64             suite.addTest(test_module.suite())
       
    65         else:
       
    66             suite.addTest(unittest.defaultTestLoader.loadTestsFromModule(test_module))
       
    67             try:            
       
    68                 suite.addTest(doctest.DocTestSuite(test_module, 
       
    69                                                    checker=doctestOutputChecker,
       
    70                                                    runner=DocTestRunner))
       
    71             except ValueError:
       
    72                 # No doc tests in tests.py
       
    73                 pass
       
    74     return suite
       
    75 
       
    76 def build_test(label):
       
    77     """Construct a test case a test with the specified label. Label should 
       
    78     be of the form model.TestClass or model.TestClass.test_method. Returns
       
    79     an instantiated test or test suite corresponding to the label provided.
       
    80         
       
    81     """
       
    82     parts = label.split('.')
       
    83     if len(parts) < 2 or len(parts) > 3:
       
    84         raise ValueError("Test label '%s' should be of the form app.TestCase or app.TestCase.test_method" % label)
       
    85     
       
    86     app_module = get_app(parts[0])
       
    87     TestClass = getattr(app_module, parts[1], None)
       
    88 
       
    89     # Couldn't find the test class in models.py; look in tests.py
       
    90     if TestClass is None:
       
    91         test_module = get_tests(app_module)
       
    92         if test_module:
       
    93             TestClass = getattr(test_module, parts[1], None)
       
    94 
       
    95     if len(parts) == 2: # label is app.TestClass
       
    96         try:
       
    97             return unittest.TestLoader().loadTestsFromTestCase(TestClass)
       
    98         except TypeError:
       
    99             raise ValueError("Test label '%s' does not refer to a test class" % label)            
       
   100     else: # label is app.TestClass.test_method
       
   101         return TestClass(parts[2])
       
   102 
       
   103 def run_tests(test_labels, verbosity=1, interactive=True, extra_tests=[]):
       
   104     """
       
   105     Run the unit tests for all the test labels in the provided list.
       
   106     Labels must be of the form:
       
   107      - app.TestClass.test_method
       
   108         Run a single specific test method
       
   109      - app.TestClass
       
   110         Run all the test methods in a given class
       
   111      - app
       
   112         Search for doctests and unittests in the named application.
       
   113 
       
   114     When looking for tests, the test runner will look in the models and
       
   115     tests modules for the application.
       
   116     
       
   117     A list of 'extra' tests may also be provided; these tests
       
   118     will be added to the test suite.
       
   119     
       
   120     Returns the number of tests that failed.
       
   121     """
       
   122     setup_test_environment()
       
   123     
       
   124     settings.DEBUG = False    
       
   125     suite = unittest.TestSuite()
       
   126     
       
   127     if test_labels:
       
   128         for label in test_labels:
       
   129             if '.' in label:
       
   130                 suite.addTest(build_test(label))
       
   131             else:
       
   132                 app = get_app(label)
       
   133                 suite.addTest(build_suite(app))
       
   134     else:
       
   135         for app in get_apps():
       
   136             suite.addTest(build_suite(app))
       
   137     
       
   138     for test in extra_tests:
       
   139         suite.addTest(test)
       
   140 
       
   141     old_name = settings.DATABASE_NAME
       
   142     create_test_db(verbosity, autoclobber=not interactive)
       
   143     result = unittest.TextTestRunner(verbosity=verbosity).run(suite)
       
   144     destroy_test_db(old_name, verbosity)
       
   145     
       
   146     teardown_test_environment()
       
   147     
       
   148     return len(result.failures) + len(result.errors)