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

Last change on this file since 8099 was 8099, checked in by habili, 12 years ago

Now uses revision number from the config file instead of relying on SVN.

File size: 6.7 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"""
7
8# Author: Mark Pilgrim
9# Modified by Ole Nielsen
10
11import unittest
12import os
13import sys
14import tempfile
15import time
16import anuga.config as config
17from anuga.utilities.terminal_width import terminal_width
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
22exclude_files = []
23
24# Directories that should not be searched for test files.
25exclude_dirs = ['pypar_dist',  'shallow_water_balanced',  'structures', # Special requirements
26                '.svn',          # subversion
27                'props', 'wcprops', 'prop-base', 'text-base', 'tmp']
28
29
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
38    p_width = page_width - 1            # set page width
39    if p_width is None:
40        p_width = 132                   # default page width
41
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))
49    c_width += 2                        # 2 column padding
50
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)
59        print '%-*s' % (c_width-1, name),
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
70def get_test_files(path):
71    """ 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    Don't include any files in and below forbidden directories.
75
76    """
77    walk = os.walk(path)
78
79    test_files = []
80    path_files = []
81
82    for (dirpath, dirnames, filenames) in walk:
83        # exclude forbidden directories
84        for e_dir in exclude_dirs:
85            try:
86                dirnames.remove(e_dir)
87            except ValueError:
88                pass
89
90        # check for test_*.py files
91        for filename in filenames:
92            if filename.startswith('test_') and filename.endswith('.py'):
93                test_files.append(filename)
94                if dirpath not in path_files:
95                    path_files.append(dirpath)
96
97    return test_files, path_files
98
99
100def regressionTest(test_verbose=False):
101    # start off with where we are
102    path = os.getcwd()
103    print
104    print 'Testing path: %s' % path
105
106    # get the terminal width
107    term_width = terminal_width()
108
109    # explain what we are doing
110    print
111    print "The following directories will be skipped over:"
112    exclude_dirs.sort()
113    list_names(exclude_dirs, page_width=term_width)
114
115    # get all test_*.py and enclosing directories
116    test_files, path_files = get_test_files(path)
117    path_files.sort()
118
119    files = [x for x in test_files if not x == 'test_all.py']
120    files.sort()        # Ensure same order on all platforms
121
122    print
123    print 'Paths searched:'
124    list_names(path_files, os.path.basename, page_width=term_width)
125
126    print   
127    print 'Files tested:'
128    list_names(files, page_width=term_width)
129    print
130
131    # update system path with found paths
132    for path in path_files:
133        sys.path.append(path)
134   
135    # exclude files that we can't handle
136    for file in exclude_files:
137        print 'WARNING: File '+ file + ' to be excluded from testing'
138        try:
139            files.remove(file)
140        except ValueError, e:
141            msg = 'File "%s" was not found in test suite.\n' % file
142            msg += 'Original error is "%s"\n' % e
143            msg += 'Perhaps it should be removed from exclude list?'
144            raise Exception, msg
145
146    # import all test_*.py files
147    # NOTE: This implies that test_*.py files MUST HAVE UNIQUE NAMES!
148    filenameToModuleName = lambda f: os.path.splitext(f)[0]
149    moduleNames = map(filenameToModuleName, files)
150    modules = map(__import__, moduleNames)
151
152    # Fix up the system path
153    for file in path_files:
154        sys.path.remove(file)
155
156    # bundle up all the tests
157    load = unittest.defaultTestLoader.loadTestsFromModule
158    testCaseClasses = map(load, modules)
159
160    if test_verbose is True:
161        # Test the code by setting verbose to True.
162        # The test cases have to be set up for this to work.
163        # See test data manager for an example.
164        for test_suite in testCaseClasses:
165            for tests in test_suite._tests:
166                # tests is of class TestSuite
167                if len(tests._tests) > 1:
168                    # these are the test functions
169                    try:
170                        # Calls class method set_verbose in test case classes
171                        tests._tests[0].set_verbose()
172                    except:
173                        pass                # No all classes have set_verbose
174
175    return unittest.TestSuite(testCaseClasses)
176
177
178##
179# @brief Check that the environment is sane.
180# @note Stops here if there is an error.
181def check_anuga_import():
182    try:
183        # importing something that loads quickly
184        import anuga.anuga_exceptions
185    except ImportError:
186        print "Python cannot import ANUGA module."
187        print "Check you have followed all steps of its installation."
188        import sys
189        sys.exit()
190
191
192if __name__ == '__main__':
193    check_anuga_import()
194
195    if len(sys.argv) > 1 and sys.argv[1][0].upper() == 'V':
196        test_verbose = True
197        saveout = sys.stdout
198        filename = ".temp"
199        fid = open(filename, 'w')
200        sys.stdout = fid
201    else:
202        test_verbose = False
203    suite = regressionTest(test_verbose)
204    runner = unittest.TextTestRunner() #verbosity=2
205    runner.run(suite)
206
207    # timestamp at the end
208    timestamp = time.asctime()
209    version = config.major_revision
210    print
211    print 'Finished at %s, version %s' % (timestamp, version)
212
213    # Cleaning up
214    if len(sys.argv) > 1 and sys.argv[1][0].upper() == 'V':
215        sys.stdout = saveout
216        #fid.close() # This was causing an error in windows
217        #os.remove(filename)
218
219   
220    if sys.platform == 'win32':
221        raw_input('Press the RETURN key')
Note: See TracBrowser for help on using the repository browser.