Home | History | Annotate | Download | only in afe
      1 import common
      2 import os, doctest, glob, sys
      3 from django.conf import settings
      4 from django.db import connection
      5 import 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 
     18 class 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