3 bup_python="$(dirname "$0")/cmd/bup-python"
4 exec "$bup_python" "$0" ${1+"$@"}
9 # Copyright (C)2007-2012 Versabanq Innovations Inc. and contributors.
10 # Licensed under the GNU Library General Public License, version 2.
11 # See the included file named LICENSE for license information.
12 # You can get wvtest from: http://github.com/apenwarr/wvtest
21 _start_dir = os.getcwd()
24 # Why do we do we need the "!= main" check? Because if you run
25 # wvtest.py as a main program and it imports your test files, then
26 # those test files will try to import the wvtest module recursively.
27 # That actually *works* fine, because we don't run this main program
28 # when we're imported as a module. But you end up with two separate
29 # wvtest modules, the one that gets imported, and the one that's the
30 # main program. Each of them would have duplicated global variables
31 # (most importantly, wvtest._registered), and so screwy things could
32 # happen. Thus, we make the main program module *totally* different
33 # from the imported module. Then we import wvtest (the module) into
34 # wvtest (the main program) here and make sure to refer to the right
35 # versions of global variables.
37 # All this is done just so that wvtest.py can be a single file that's
38 # easy to import into your own applications.
39 if __name__ != '__main__': # we're imported as a module
45 """ Use this decorator (@wvtest) in front of any function you want to
46 run as part of the unit test suite. Then run:
47 python wvtest.py path/to/yourtest.py [other test.py files...]
48 to run all the @wvtest functions in the given file(s).
50 _registered.append(func)
54 def _result(msg, tb, code):
59 (filename, line, func, text) = tb
60 filename = os.path.basename(filename)
61 msg = re.sub(r'\s+', ' ', str(msg))
63 print '! %-70s %s' % ('%s:%-4d %s' % (filename, line, msg),
68 def _caller_stack(wv_call_depth):
69 # Without the chdir, the source text lookup may fail
73 return traceback.extract_stack()[-(wv_call_depth + 2)]
78 def _check(cond, msg = 'unknown', tb = None):
79 if tb == None: tb = _caller_stack(2)
81 _result(msg, tb, 'ok')
83 _result(msg, tb, 'FAILED')
86 _code_rx = re.compile(r'^\w+\((.*)\)(\s*#.*)?$')
88 text = _caller_stack(2)[3]
89 return _code_rx.sub(r'\1', text)
92 filename = _caller_stack(1)[0]
93 sys.stderr.write('Testing \"' + message + '\" in ' + filename + ':\n')
96 ''' Issues a notification. '''
97 return _result(message, _caller_stack(1), 'ok')
99 def WVPASS(cond = True):
100 ''' Counts a test failure unless cond is true. '''
101 return _check(cond, _code())
103 def WVFAIL(cond = True):
104 ''' Counts a test failure unless cond is false. '''
105 return _check(not cond, 'NOT(%s)' % _code())
108 ''' Counts a test failure unless a == b. '''
109 return _check(a == b, '%s == %s' % (repr(a), repr(b)))
112 ''' Counts a test failure unless a != b. '''
113 return _check(a != b, '%s != %s' % (repr(a), repr(b)))
116 ''' Counts a test failure unless a < b. '''
117 return _check(a < b, '%s < %s' % (repr(a), repr(b)))
120 ''' Counts a test failure unless a <= b. '''
121 return _check(a <= b, '%s <= %s' % (repr(a), repr(b)))
124 ''' Counts a test failure unless a > b. '''
125 return _check(a > b, '%s > %s' % (repr(a), repr(b)))
128 ''' Counts a test failure unless a >= b. '''
129 return _check(a >= b, '%s >= %s' % (repr(a), repr(b)))
131 def WVEXCEPT(etype, func, *args, **kwargs):
132 ''' Counts a test failure unless func throws an 'etype' exception.
133 You have to spell out the function name and arguments, rather than
134 calling the function yourself, so that WVEXCEPT can run before
135 your test code throws an exception.
138 func(*args, **kwargs)
140 return _check(True, 'EXCEPT(%s)' % _code())
142 _check(False, 'EXCEPT(%s)' % _code())
145 return _check(False, 'EXCEPT(%s)' % _code())
159 def wvfailure_count():
162 def _check_unfinished():
164 for func in _registered:
165 print 'WARNING: not run: %r' % (func,)
166 WVFAIL('wvtest_main() not called')
170 atexit.register(_check_unfinished)
173 def _run_in_chdir(path, func, *args, **kwargs):
178 sys.path += [path, os.path.split(path)[0]]
179 return func(*args, **kwargs)
185 if sys.version_info >= (2,6,0):
186 _relpath = os.path.relpath;
188 # Implementation for Python 2.5, taken from CPython (tag v2.6,
189 # file Lib/posixpath.py, hg-commit 95fff5a6a276). Update
190 # ./LICENSE When this code is eventually removed.
191 def _relpath(path, start=os.path.curdir):
193 raise ValueError("no path specified")
195 start_list = os.path.abspath(start).split(os.path.sep)
196 path_list = os.path.abspath(path).split(os.path.sep)
198 # Work out how much of the filepath is shared by start and path.
199 i = len(os.path.commonprefix([start_list, path_list]))
201 rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
204 return os.path.join(*rel_list)
207 def _runtest(fname, f):
208 mod = inspect.getmodule(f)
209 relpath = _relpath(mod.__file__, os.getcwd()).replace('.pyc', '.py')
211 print 'Testing "%s" in %s:' % (fname, relpath)
214 _run_in_chdir(os.path.split(mod.__file__)[0], f)
215 except Exception as e:
217 print traceback.format_exc()
218 tb = sys.exc_info()[2]
219 wvtest._result(e, traceback.extract_tb(tb)[1], 'EXCEPTION')
222 def _run_registered_tests():
223 import wvtest as _wvtestmod
224 while _wvtestmod._registered:
225 t = _wvtestmod._registered.pop(0)
226 _runtest(t.func_name, t)
230 def wvtest_main(extra_testfiles=tuple()):
231 import wvtest as _wvtestmod
232 _run_registered_tests()
233 for modname in extra_testfiles:
234 if not os.path.exists(modname):
235 print 'Skipping: %s' % modname
237 if modname.endswith('.py'):
238 modname = modname[:-3]
239 print 'Importing: %s' % modname
240 path, mod = os.path.split(os.path.abspath(modname))
241 nicename = modname.replace(os.path.sep, '.')
242 while nicename.startswith('.'):
243 nicename = modname[1:]
244 _run_in_chdir(path, __import__, nicename, None, None, [])
245 _run_registered_tests()
247 print 'WvTest: %d tests, %d failures.' % (_wvtestmod._tests,
251 if __name__ == '__main__':
252 import wvtest as _wvtestmod
253 sys.modules['wvtest'] = _wvtestmod
254 sys.modules['wvtest.wvtest'] = _wvtestmod
256 wvtest_main(sys.argv[1:])