source: branches/numpy/anuga/test_all.py @ 7024

Last change on this file since 7024 was 6904, checked in by rwilson, 16 years ago

Finished back-merge from Numeric trunk to numpy branch (and some code the other way).

File size: 6.7 KB
RevLine 
[3464]1"""Regression testing framework
2This module will search for scripts in the same directory named
3test_*.py.  Each such script should be a test suite that tests a
4module through PyUnit. This script will aggregate all
5found test suites into one big test suite and run them all at once.
6"""
7
8# Author: Mark Pilgrim
9# Modified by Ole Nielsen
10
11import unittest
12import os
13import sys
[4414]14import tempfile
[6220]15import time
16import anuga.utilities.system_tools as aust
[6304]17from anuga.utilities.terminal_width import terminal_width
[3464]18
19
20#List files that should be excluded from the testing process.
21#E.g. if they are known to fail and under development
[3573]22exclude_files = []
[4796]23
[6086]24# Directories that should not be searched for test files.
[6218]25exclude_dirs = ['pypar_dist',                        # Special requirements
26                '.svn',                              # subversion
27                'props', 'wcprops', 'prop-base', 'text-base', 'tmp']
[4796]28
[3464]29
[6218]30##
31# @brief List a string sequence on the screen in columns.
32# @param names Sequence of strings to list.
33# @param func Function to apply to each string in sequence.
34# @param col_width Force columns to this width (default calculated).
35# @param page_width Set displayable page width to this (default 132).
36def list_names(names, func=None, col_width=None, page_width=None):
37    # set defaults
[6304]38    p_width = page_width - 1            # set page width
[6218]39    if p_width is None:
40        p_width = 132                   # default page width
[3464]41
[6218]42    c_width = col_width                 # set column width
43    if c_width is None:
44        c_width = 0
45        for name in names:
46            if func:
47                name = func(name)
48            c_width = max(c_width, len(name))
[6304]49    c_width += 2                        # 2 column padding
[6086]50
[6218]51    # calculate number of columns allowed
52    max_columns = int(p_width / c_width)
53
54    # print columns
55    column = 0
56    for name in names:
57        if func:
58            name = func(name)
[6304]59        print '%-*s' % (c_width-1, name),
[6218]60        column += 1
61        if column >= max_columns:
62            column = 0
63            print
64
65    # if last line not finished, end it here
66    if column > 0:
67        print
68
69
70##
71# @brief Get 'test_*.py' files and paths to directories.
72# @param path Path to directory to start walk in.
73# @return A tuple (<files>, <dirs>).
74# @note Don't include any files in and below forbidden directories.
[3464]75def get_test_files(path):
[6218]76    walk = os.walk(path)
[3464]77
78    test_files = []
79    path_files = []
80
[6218]81    for (dirpath, dirnames, filenames) in walk:
82        # exclude forbidden directories
83        for e_dir in exclude_dirs:
84            try:
85                dirnames.remove(e_dir)
86            except ValueError:
87                pass
[6086]88
[6218]89        # check for test_*.py files
90        for filename in filenames:
91            if filename.startswith('test_') and filename.endswith('.py'):
92                test_files.append(filename)
93                if dirpath not in path_files:
94                    path_files.append(dirpath)
95
[4804]96    return test_files, path_files
[3464]97
98
[4414]99def regressionTest(test_verbose=False):
[6218]100    # start off with where we are
[3464]101    path = os.getcwd()
[6218]102    print
103    print 'Testing path: %s' % path
104
[6304]105    # get the terminal width
106    term_width = terminal_width()
107
[6218]108    # explain what we are doing
109    print
110    print "The following directories will be skipped over:"
111    exclude_dirs.sort()
[6304]112    list_names(exclude_dirs, page_width=term_width)
[6218]113
114    # get all test_*.py and enclosing directories
[3464]115    test_files, path_files = get_test_files(path)
[4804]116
[3464]117    files = [x for x in test_files if not x == 'test_all.py']
[6218]118    files.sort()        # Ensure same order on all platforms
[4804]119
[4461]120    print
[6215]121    print 'Paths searched:'
[6304]122    list_names(path_files, os.path.basename, page_width=term_width)
[6218]123
[6215]124    print   
[6218]125    print 'Files tested:'
[6304]126    list_names(files, page_width=term_width)
[6220]127    print
[6215]128
[6218]129    # update system path with found paths
130    for path in path_files:
131        sys.path.append(path)
132   
133    # exclude files that we can't handle
134    for file in exclude_files:
135        print 'WARNING: File '+ file + ' to be excluded from testing'
136        try:
137            files.remove(file)
138        except ValueError, e:
139            msg = 'File "%s" was not found in test suite.\n' % file
140            msg += 'Original error is "%s"\n' % e
141            msg += 'Perhaps it should be removed from exclude list?'
142            raise Exception, msg
[3464]143
[6218]144    # import all test_*.py files
145    # NOTE: This implies that test_*.py files MUST HAVE UNIQUE NAMES!
[3464]146    filenameToModuleName = lambda f: os.path.splitext(f)[0]
147    moduleNames = map(filenameToModuleName, files)
148    modules = map(__import__, moduleNames)
[6086]149
[3464]150    # Fix up the system path
151    for file in path_files:
152        sys.path.remove(file)
[6086]153
[6218]154    # bundle up all the tests
[3464]155    load = unittest.defaultTestLoader.loadTestsFromModule
[4414]156    testCaseClasses = map(load, modules)
[4418]157
[4414]158    if test_verbose is True:
[4415]159        # Test the code by setting verbose to True.
160        # The test cases have to be set up for this to work.
161        # See test data manager for an example.
[4414]162        for test_suite in testCaseClasses:
163            for tests in test_suite._tests:
[4418]164                # tests is of class TestSuite
165                if len(tests._tests) > 1:
[4414]166                    # these are the test functions
167                    try:
[6086]168                        # Calls class method set_verbose in test case classes
[4414]169                        tests._tests[0].set_verbose()
170                    except:
[6086]171                        pass                # No all classes have set_verbose
[6218]172
[4414]173    return unittest.TestSuite(testCaseClasses)
[3464]174
[6086]175
[6218]176##
177# @brief Check that the environment is sane.
178# @note Stops here if there is an error.
[4763]179def check_anuga_import():
180    try:
181        # importing something that loads quickly
182        import anuga.utilities.anuga_exceptions
183    except ImportError:
184        print "Python cannot import ANUGA module."
185        print "Check you have followed all steps of its installation."
[6086]186        import sys
187        sys.exit()
[4763]188
[6086]189
[3464]190if __name__ == '__main__':
[4763]191    check_anuga_import()
[6086]192
[4414]193    if len(sys.argv) > 1 and sys.argv[1][0].upper() == 'V':
194        test_verbose = True
[6086]195        saveout = sys.stdout
[4414]196        filename = ".temp"
197        fid = open(filename, 'w')
198        sys.stdout = fid
199    else:
[6086]200        test_verbose = False
[4414]201    suite = regressionTest(test_verbose)
[3464]202    runner = unittest.TextTestRunner() #verbosity=2
203    runner.run(suite)
[6086]204
[6220]205    # timestamp at the end
206    timestamp = time.asctime()
207    version = aust.get_revision_number()
208    print
209    print 'Finished at %s, version %s' % (timestamp, version)
210
[4414]211    # Cleaning up
212    if len(sys.argv) > 1 and sys.argv[1][0].upper() == 'V':
[6086]213        sys.stdout = saveout
[4414]214        #fid.close() # This was causing an error in windows
215        #os.remove(filename)
216
[6553]217   
218    if sys.platform == 'win32':
[6904]219        raw_input('Press the RETURN key')
Note: See TracBrowser for help on using the repository browser.