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

Last change on this file since 8691 was 8440, checked in by steve, 12 years ago

Commiting validation files

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