~kkubasik/django/aggregation-branch

« back to all changes in this revision

Viewing changes to tests/runtests.py

  • Committer: adrian
  • Date: 2006-05-02 01:31:56 UTC
  • Revision ID: vcs-imports@canonical.com-20060502013156-2941fcd40d080649
MERGED MAGIC-REMOVAL BRANCH TO TRUNK. This change is highly backwards-incompatible. Please read http://code.djangoproject.com/wiki/RemovingTheMagic for upgrade instructions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
# and Django aims to work with Python 2.3+.
8
8
import doctest
9
9
 
10
 
APP_NAME = 'testapp'
 
10
MODEL_TESTS_DIR_NAME = 'modeltests'
11
11
OTHER_TESTS_DIR = "othertests"
12
12
TEST_DATABASE_NAME = 'django_test_db'
13
13
 
18
18
        'description': description,
19
19
    })
20
20
 
21
 
MODEL_DIR = os.path.join(os.path.dirname(__file__), APP_NAME, 'models')
 
21
MODEL_TEST_DIR = os.path.join(os.path.dirname(__file__), MODEL_TESTS_DIR_NAME)
22
22
 
23
23
def get_test_models():
24
 
    return [f[:-3] for f in os.listdir(MODEL_DIR) if f.endswith('.py') and not f.startswith('__init__')]
 
24
    return [f for f in os.listdir(MODEL_TEST_DIR) if not f.startswith('__init__') and not f.startswith('.')]
25
25
 
26
26
class DjangoDoctestRunner(doctest.DocTestRunner):
27
27
    def __init__(self, verbosity_level, *args, **kwargs):
39
39
            "Code: %r\nLine: %s\nExpected: %r\nGot: %r" % (example.source.strip(), example.lineno, example.want, got))
40
40
 
41
41
    def report_unexpected_exception(self, out, test, example, exc_info):
 
42
        from django.db import transaction
42
43
        tb = ''.join(traceback.format_exception(*exc_info)[1:])
43
44
        log_error(test.name, "API test raised an exception",
44
45
            "Code: %r\nLine: %s\nException: %s" % (example.source.strip(), example.lineno, tb))
 
46
        # Rollback, in case of database errors. Otherwise they'd have
 
47
        # side effects on other tests.
 
48
        transaction.rollback_unless_managed()
45
49
 
46
50
normalize_long_ints = lambda s: re.sub(r'(?<![\w])(\d+)L(?![\w])', '\\1', s)
47
51
 
68
72
 
69
73
    def run_tests(self):
70
74
        from django.conf import settings
71
 
        from django.core.db import db
72
 
        from django.core import management, meta
73
 
 
74
 
        # Manually set INSTALLED_APPS to point to the test app.
75
 
        settings.INSTALLED_APPS = (APP_NAME,)
 
75
 
 
76
        # Manually set INSTALLED_APPS to point to the test models.
 
77
        settings.INSTALLED_APPS = [MODEL_TESTS_DIR_NAME + '.' + a for a in get_test_models()]
 
78
 
 
79
        # Manually set DEBUG = False.
 
80
        settings.DEBUG = False
 
81
 
 
82
        from django.db import connection
 
83
        from django.core import management
 
84
        import django.db.models
76
85
 
77
86
        # Determine which models we're going to test.
78
87
        test_models = get_test_models()
 
88
        if 'othertests' in self.which_tests:
 
89
            self.which_tests.remove('othertests')
 
90
            run_othertests = True
 
91
            if not self.which_tests:
 
92
                test_models = []
 
93
        else:
 
94
            run_othertests = not self.which_tests
 
95
 
79
96
        if self.which_tests:
80
97
            # Only run the specified tests.
81
98
            bad_models = [m for m in self.which_tests if m not in test_models]
96
113
            # Create the test database and connect to it. We need autocommit()
97
114
            # because PostgreSQL doesn't allow CREATE DATABASE statements
98
115
            # within transactions.
99
 
            cursor = db.cursor()
 
116
            cursor = connection.cursor()
100
117
            try:
101
 
                db.connection.autocommit(1)
 
118
                connection.connection.autocommit(1)
102
119
            except AttributeError:
103
120
                pass
104
121
            self.output(1, "Creating test database")
113
130
                else:
114
131
                    print "Tests cancelled."
115
132
                    return
116
 
        db.close()
 
133
        connection.close()
117
134
        old_database_name = settings.DATABASE_NAME
118
135
        settings.DATABASE_NAME = TEST_DATABASE_NAME
119
136
 
120
137
        # Initialize the test database.
121
 
        cursor = db.cursor()
122
 
        self.output(1, "Initializing test database")
123
 
        management.init()
 
138
        cursor = connection.cursor()
124
139
 
125
140
        # Run the tests for each test model.
126
141
        self.output(1, "Running app tests")
127
142
        for model_name in test_models:
128
143
            self.output(1, "%s model: Importing" % model_name)
129
144
            try:
130
 
                mod = meta.get_app(model_name)
 
145
                # TODO: Abstract this into a meta.get_app() replacement?
 
146
                mod = __import__(MODEL_TESTS_DIR_NAME + '.' + model_name + '.models', '', '', [''])
131
147
            except Exception, e:
132
148
                log_error(model_name, "Error while importing", ''.join(traceback.format_exception(*sys.exc_info())[1:]))
133
149
                continue
134
 
            self.output(1, "%s model: Installing" % model_name)
135
 
            management.install(mod)
136
 
 
137
 
            # Run the API tests.
138
 
            p = doctest.DocTestParser()
139
 
            test_namespace = dict([(m._meta.module_name, getattr(mod, m._meta.module_name)) for m in mod._MODELS])
140
 
            dtest = p.get_doctest(mod.API_TESTS, test_namespace, model_name, None, None)
141
 
            # Manually set verbose=False, because "-v" command-line parameter
142
 
            # has side effects on doctest TestRunner class.
143
 
            runner = DjangoDoctestRunner(verbosity_level=verbosity_level, verbose=False)
144
 
            self.output(1, "%s model: Running tests" % model_name)
145
 
            try:
 
150
 
 
151
            if not getattr(mod, 'error_log', None):
 
152
                # Model is not marked as an invalid model
 
153
                self.output(1, "%s model: Installing" % model_name)
 
154
                management.install(mod)
 
155
 
 
156
                # Run the API tests.
 
157
                p = doctest.DocTestParser()
 
158
                test_namespace = dict([(m._meta.object_name, m) \
 
159
                                        for m in django.db.models.get_models(mod)])
 
160
                dtest = p.get_doctest(mod.API_TESTS, test_namespace, model_name, None, None)
 
161
                # Manually set verbose=False, because "-v" command-line parameter
 
162
                # has side effects on doctest TestRunner class.
 
163
                runner = DjangoDoctestRunner(verbosity_level=verbosity_level, verbose=False)
 
164
                self.output(1, "%s model: Running tests" % model_name)
146
165
                runner.run(dtest, clear_globs=True, out=sys.stdout.write)
147
 
            finally:
148
 
                # Rollback, in case of database errors. Otherwise they'd have
149
 
                # side effects on other tests.
150
 
                db.rollback()
151
 
 
152
 
        if not self.which_tests:
 
166
            else:
 
167
                # Check that model known to be invalid is invalid for the right reasons.
 
168
                self.output(1, "%s model: Validating" % model_name)
 
169
 
 
170
                from cStringIO import StringIO
 
171
                s = StringIO()
 
172
                count = management.get_validation_errors(s, mod)
 
173
                s.seek(0)
 
174
                error_log = s.read()
 
175
                actual = error_log.split('\n')
 
176
                expected = mod.error_log.split('\n')
 
177
 
 
178
                unexpected = [err for err in actual if err not in expected]
 
179
                missing = [err for err in expected if err not in actual]
 
180
 
 
181
                if unexpected or missing:
 
182
                    unexpected_log = '\n'.join(unexpected)
 
183
                    missing_log = '\n'.join(missing)
 
184
                    log_error(model_name,
 
185
                        "Validator found %d validation errors, %d expected" % (count, len(expected) - 1),
 
186
                        "Missing errors:\n%s\n\nUnexpected errors:\n%s" % (missing_log, unexpected_log))
 
187
 
 
188
        if run_othertests:
153
189
            # Run the non-model tests in the other tests dir
154
190
            self.output(1, "Running other tests")
155
191
            other_tests_dir = os.path.join(os.path.dirname(__file__), OTHER_TESTS_DIR)
180
216
        # to do so, because it's not allowed to delete a database while being
181
217
        # connected to it.
182
218
        if settings.DATABASE_ENGINE != "sqlite3":
183
 
            db.close()
 
219
            connection.close()
184
220
            settings.DATABASE_NAME = old_database_name
185
 
            cursor = db.cursor()
 
221
            cursor = connection.cursor()
186
222
            self.output(1, "Deleting test database")
187
223
            try:
188
 
                db.connection.autocommit(1)
 
224
                connection.connection.autocommit(1)
189
225
            except AttributeError:
190
226
                pass
191
227
            else: