Django

Code

root/django/trunk/django/test/simple.py

Revision 8296, 5.6 kB (checked in by russellm, 3 months ago)

Fixed #5461 -- Refactored the database backend code to use classes for the creation and introspection modules. Introduces a new validation module for DB-specific validation. This is a backwards incompatible change; see the wiki for details.

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