source: trunk/anuga_core/source/anuga/test_all.py @ 8272

Last change on this file since 8272 was 8174, checked in by wilsonr, 14 years ago

Changes as per ticket 362.

File size: 7.2 KB
Line 
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
7Usage: test_all.py [<options>]
8
9where <options> is zero or more of:
10      -q         be quiet, minimal output to screen, write to ./.temp
11      --quiet    same as above
12      -v         be verbose to screen, more '-v's makes more verbose
13      --verbose  same as above
14You may do things like "test_all.py -q -v -v".
15"""
16
17# Author: Mark Pilgrim
18# Modified by Ole Nielsen
19
20import unittest
21import os
22import sys
23import tempfile
24import time
25import anuga.config as config
26from anuga.utilities.terminal_width import terminal_width
27
28
29#List files that should be excluded from the testing process.
30#E.g. if they are known to fail and under development
31exclude_files = []
32
33# Directories that should not be searched for test files.
34exclude_dirs = ['shallow_water_balanced' , # Special requirements
35                '.svn',          # subversion
36                'props', 'wcprops', 'prop-base', 'text-base', 'tmp']
37
38# name of file to capture stdout in
39CaptureFilename = '.temp'
40
41
42def list_names(names, func=None, col_width=None, page_width=None):
43    # set defaults
44    p_width = page_width - 1            # set page width
45    if p_width is None:
46        p_width = 132                   # default page width
47
48    c_width = col_width                 # set column width
49    if c_width is None:
50        c_width = 0
51        for name in names:
52            if func:
53                name = func(name)
54            c_width = max(c_width, len(name))
55    c_width += 2                        # 2 column padding
56
57    # calculate number of columns allowed
58    max_columns = int(p_width / c_width)
59
60    # print columns
61    column = 0
62    for name in names:
63        if func:
64            name = func(name)
65        print '%-*s' % (c_width-1, name),
66        column += 1
67        if column >= max_columns:
68            column = 0
69            print
70
71    # if last line not finished, end it here
72    if column > 0:
73        print
74
75
76def get_test_files(path):
77    """ Get 'test_*.py' files and paths to directories.
78    param path Path to directory to start walk in.
79    @return A tuple (<files>, <dirs>).
80    Don't include any files in and below forbidden directories.
81
82    """
83    walk = os.walk(path)
84
85    test_files = []
86    path_files = []
87
88    for (dirpath, dirnames, filenames) in walk:
89        # exclude forbidden directories
90        for e_dir in exclude_dirs:
91            try:
92                dirnames.remove(e_dir)
93            except ValueError:
94                pass
95
96        # check for test_*.py files
97        for filename in filenames:
98            if filename.startswith('test_') and filename.endswith('.py'):
99                test_files.append(filename)
100                if dirpath not in path_files:
101                    path_files.append(dirpath)
102
103    return test_files, path_files
104
105
106def regressionTest(test_verbose=False):
107    # start off with where we are
108    path = os.getcwd()
109    print
110    print 'Testing path: %s' % path
111
112    # get the terminal width
113    term_width = terminal_width()
114
115    # explain what we are doing
116    print
117    print "The following directories will be skipped over:"
118    exclude_dirs.sort()
119    list_names(exclude_dirs, page_width=term_width)
120
121    # get all test_*.py and enclosing directories
122    test_files, path_files = get_test_files(path)
123    path_files.sort()
124
125    files = [x for x in test_files if not x == 'test_all.py']
126    files.sort()        # Ensure same order on all platforms
127
128    print
129    print 'Paths searched:'
130    list_names(path_files, os.path.basename, page_width=term_width)
131
132    print   
133    print 'Files tested:'
134    list_names(files, page_width=term_width)
135    print
136
137    # update system path with found paths
138    for path in path_files:
139        sys.path.append(path)
140   
141    # exclude files that we can't handle
142    for file in exclude_files:
143        print 'WARNING: File '+ file + ' to be excluded from testing'
144        try:
145            files.remove(file)
146        except ValueError, e:
147            msg = 'File "%s" was not found in test suite.\n' % file
148            msg += 'Original error is "%s"\n' % e
149            msg += 'Perhaps it should be removed from exclude list?'
150            raise Exception, msg
151
152    # import all test_*.py files
153    # NOTE: This implies that test_*.py files MUST HAVE UNIQUE NAMES!
154    filenameToModuleName = lambda f: os.path.splitext(f)[0]
155    moduleNames = map(filenameToModuleName, files)
156    modules = map(__import__, moduleNames)
157
158    # Fix up the system path
159    for file in path_files:
160        sys.path.remove(file)
161
162    # bundle up all the tests
163    load = unittest.defaultTestLoader.loadTestsFromModule
164    testCaseClasses = map(load, modules)
165
166    if test_verbose is True:
167        # Test the code by setting verbose to True.
168        # The test cases have to be set up for this to work.
169        # See test data manager for an example.
170        for test_suite in testCaseClasses:
171            for tests in test_suite._tests:
172                # tests is of class TestSuite
173                if len(tests._tests) > 1:
174                    # these are the test functions
175                    try:
176                        # Calls class method set_verbose in test case classes
177                        tests._tests[0].set_verbose()
178                    except:
179                        pass                # No all classes have set_verbose
180
181    return unittest.TestSuite(testCaseClasses)
182
183
184def check_anuga_import():
185    try:
186        # importing something that loads quickly
187        import anuga.anuga_exceptions
188    except ImportError:
189        print "Python cannot import ANUGA module."
190        print "Check you have followed all steps of its installation."
191        import sys
192        sys.exit()
193
194
195if __name__ == '__main__':
196    from optparse import OptionParser
197
198    check_anuga_import()
199
200    # check the commandline params
201    usage = "usage: %prog [-h|-q|-v]"
202    parser = OptionParser(usage)
203    parser.add_option("-v", "--verbose",
204                      action="count", dest="verbosity", default=1,
205                      help='make the ouput even more verbose')
206    parser.add_option("-q", "--quiet",
207                      action="store_true", dest="quiet",
208                      help="capture statistics output in file '%s'"
209                           % CaptureFilename)
210    (options, args) = parser.parse_args()
211
212    if len(args) > 0:
213        parser.error("test_all.py doesn't take any parameters.  "
214                     "Do 'test_all.py -h' to see the help.")
215
216    if options.quiet:
217        saveout = sys.stdout
218        filename = CaptureFilename
219        fid = open(filename, 'w')
220        sys.stdout = fid
221
222    # run the tests
223    suite = regressionTest(options.quiet)
224    runner = unittest.TextTestRunner(verbosity=options.verbosity)
225    runner.run(suite)
226
227    # timestamp at the end
228    timestamp = time.asctime()
229    version = config.major_revision
230    print '\nFinished at %s, version %s' % (timestamp, version)
231
232    # Cleaning up
233    if options.verbosity < 1:
234        sys.stdout = saveout
235        #fid.close() # This was causing an error in windows
236        #os.remove(filename)
237   
238    if sys.platform == 'win32':
239        raw_input('Press the RETURN key')
Note: See TracBrowser for help on using the repository browser.