import common import os, doctest, glob, sys from django.conf import settings from django.db import connection import django.test.utils # doctest takes a copy+paste log of a Python interactive session, runs a Python # interpreter, and replays all the inputs from the log, checking that the # outputs all match the log. This allows us to easily test behavior and # document functions at the same time, since the log shows exactly how functions # are called and what their outputs look like. See # http://www.python.org/doc/2.4.3/lib/module-doctest.html for more details. # In this file, we run doctest on all files found in the doctests/ directory. # We use django.test.utils to run the tests against a fresh test database every # time. class DoctestRunner(object): _PRINT_AFTER = 'Ran %d tests from %s' def __init__(self, app_dir, app_module_name): self._app_dir = app_dir self._app_module_name = app_module_name def _get_doctest_paths(self): doctest_dir = os.path.join(self._app_dir, 'doctests') doctest_paths = [os.path.join(doctest_dir, filename) for filename in os.listdir(doctest_dir) if not filename.startswith('.') if not filename.endswith('~')] return sorted(doctest_paths) def _get_modules(self): modules = [] module_names = [os.path.basename(filename)[:-3] for filename in glob.glob(os.path.join(self._app_dir, '*.py')) if '__init__' not in filename and 'test.py' not in filename] # TODO: use common.setup_modules.import_module() app_module = __import__(self._app_module_name, globals(), locals(), module_names) for module_name in module_names: modules.append(getattr(app_module, module_name)) return modules def run_tests(self): """ module_list is ignored - we're just required to have this signature as a Django test runner. """ doctest_paths = self._get_doctest_paths() modules = self._get_modules() total_errors = 0 old_db = settings.DATABASES['default']['NAME'] django.test.utils.setup_test_environment() connection.creation.create_test_db() try: for module in modules: failures, test_count = doctest.testmod(module) print self._PRINT_AFTER % (test_count, module.__name__) total_errors += failures for path in doctest_paths: failures, test_count = doctest.testfile(path, module_relative=False) print self._PRINT_AFTER % (test_count, path) total_errors += failures finally: connection.creation.destroy_test_db(old_db) django.test.utils.teardown_test_environment() print if total_errors == 0: print 'OK' else: print 'FAIL: %d errors' % total_errors return total_errors