1import common 2import os, doctest, glob, sys 3from django.conf import settings 4from django.db import connection 5import django.test.utils 6 7# doctest takes a copy+paste log of a Python interactive session, runs a Python 8# interpreter, and replays all the inputs from the log, checking that the 9# outputs all match the log. This allows us to easily test behavior and 10# document functions at the same time, since the log shows exactly how functions 11# are called and what their outputs look like. See 12# http://www.python.org/doc/2.4.3/lib/module-doctest.html for more details. 13 14# In this file, we run doctest on all files found in the doctests/ directory. 15# We use django.test.utils to run the tests against a fresh test database every 16# time. 17 18class DoctestRunner(object): 19 _PRINT_AFTER = 'Ran %d tests from %s' 20 21 def __init__(self, app_dir, app_module_name): 22 self._app_dir = app_dir 23 self._app_module_name = app_module_name 24 25 26 def _get_doctest_paths(self): 27 doctest_dir = os.path.join(self._app_dir, 'doctests') 28 doctest_paths = [os.path.join(doctest_dir, filename) for filename 29 in os.listdir(doctest_dir) 30 if not filename.startswith('.') 31 if not filename.endswith('~')] 32 return sorted(doctest_paths) 33 34 35 def _get_modules(self): 36 modules = [] 37 module_names = [os.path.basename(filename)[:-3] 38 for filename 39 in glob.glob(os.path.join(self._app_dir, '*.py')) 40 if '__init__' not in filename 41 and 'test.py' not in filename] 42 # TODO: use common.setup_modules.import_module() 43 app_module = __import__(self._app_module_name, globals(), locals(), 44 module_names) 45 for module_name in module_names: 46 modules.append(getattr(app_module, module_name)) 47 return modules 48 49 50 def run_tests(self): 51 """ 52 module_list is ignored - we're just required to have this signature as a 53 Django test runner. 54 """ 55 doctest_paths = self._get_doctest_paths() 56 modules = self._get_modules() 57 total_errors = 0 58 old_db = settings.DATABASES['default']['NAME'] 59 django.test.utils.setup_test_environment() 60 connection.creation.create_test_db() 61 try: 62 for module in modules: 63 failures, test_count = doctest.testmod(module) 64 print self._PRINT_AFTER % (test_count, module.__name__) 65 total_errors += failures 66 for path in doctest_paths: 67 failures, test_count = doctest.testfile(path, 68 module_relative=False) 69 print self._PRINT_AFTER % (test_count, path) 70 total_errors += failures 71 finally: 72 connection.creation.destroy_test_db(old_db) 73 django.test.utils.teardown_test_environment() 74 print 75 if total_errors == 0: 76 print 'OK' 77 else: 78 print 'FAIL: %d errors' % total_errors 79 return total_errors 80