3 bup_python="$(dirname "$0")/cmd/bup-python"
4 exec "$bup_python" "$0" ${1+"$@"}
10 # Copyright (C)2007-2012 Versabanq Innovations Inc. and contributors.
11 # Licensed under the GNU Library General Public License, version 2.
12 # See the included file named LICENSE for license information.
13 # You can get wvtest from: http://github.com/apenwarr/wvtest
16 from __future__ import absolute_import
24 _start_dir = os.getcwd()
27 # Why do we do we need the "!= main" check? Because if you run
28 # wvtest.py as a main program and it imports your test files, then
29 # those test files will try to import the wvtest module recursively.
30 # That actually *works* fine, because we don't run this main program
31 # when we're imported as a module. But you end up with two separate
32 # wvtest modules, the one that gets imported, and the one that's the
33 # main program. Each of them would have duplicated global variables
34 # (most importantly, wvtest._registered), and so screwy things could
35 # happen. Thus, we make the main program module *totally* different
36 # from the imported module. Then we import wvtest (the module) into
37 # wvtest (the main program) here and make sure to refer to the right
38 # versions of global variables.
40 # All this is done just so that wvtest.py can be a single file that's
41 # easy to import into your own applications.
42 if __name__ != '__main__': # we're imported as a module
48 """ Use this decorator (@wvtest) in front of any function you want to
49 run as part of the unit test suite. Then run:
50 python wvtest.py path/to/yourtest.py [other test.py files...]
51 to run all the @wvtest functions in the given file(s).
53 _registered.append(func)
57 def _result(msg, tb, code):
62 (filename, line, func, text) = tb
63 filename = os.path.basename(filename)
64 msg = re.sub(r'\s+', ' ', str(msg))
66 print '! %-70s %s' % ('%s:%-4d %s' % (filename, line, msg),
71 def _caller_stack(wv_call_depth):
72 # Without the chdir, the source text lookup may fail
76 return traceback.extract_stack()[-(wv_call_depth + 2)]
81 def _check(cond, msg = 'unknown', tb = None):
82 if tb == None: tb = _caller_stack(2)
84 _result(msg, tb, 'ok')
86 _result(msg, tb, 'FAILED')
89 def wvcheck(cond, msg, tb = None):
90 if tb == None: tb = _caller_stack(2)
92 _result(msg, tb, 'ok')
94 _result(msg, tb, 'FAILED')
97 _code_rx = re.compile(r'^\w+\((.*)\)(\s*#.*)?$')
99 text = _caller_stack(2)[3]
100 return _code_rx.sub(r'\1', text)
102 def WVSTART(message):
103 filename = _caller_stack(1)[0]
104 sys.stderr.write('Testing \"' + message + '\" in ' + filename + ':\n')
107 ''' Issues a notification. '''
108 return _result(message, _caller_stack(1), 'ok')
110 def WVPASS(cond = True):
111 ''' Counts a test failure unless cond is true. '''
112 return _check(cond, _code())
114 def WVFAIL(cond = True):
115 ''' Counts a test failure unless cond is false. '''
116 return _check(not cond, 'NOT(%s)' % _code())
119 ''' Counts a test failure unless a == b. '''
120 return _check(a == b, '%s == %s' % (repr(a), repr(b)))
123 ''' Counts a test failure unless a != b. '''
124 return _check(a != b, '%s != %s' % (repr(a), repr(b)))
127 ''' Counts a test failure unless a < b. '''
128 return _check(a < b, '%s < %s' % (repr(a), repr(b)))
131 ''' Counts a test failure unless a <= b. '''
132 return _check(a <= b, '%s <= %s' % (repr(a), repr(b)))
135 ''' Counts a test failure unless a > b. '''
136 return _check(a > b, '%s > %s' % (repr(a), repr(b)))
139 ''' Counts a test failure unless a >= b. '''
140 return _check(a >= b, '%s >= %s' % (repr(a), repr(b)))
142 def WVEXCEPT(etype, func, *args, **kwargs):
143 ''' Counts a test failure unless func throws an 'etype' exception.
144 You have to spell out the function name and arguments, rather than
145 calling the function yourself, so that WVEXCEPT can run before
146 your test code throws an exception.
149 func(*args, **kwargs)
151 return _check(True, 'EXCEPT(%s)' % _code())
153 _check(False, 'EXCEPT(%s)' % _code())
156 return _check(False, 'EXCEPT(%s)' % _code())
170 def wvfailure_count():
173 def _check_unfinished():
175 for func in _registered:
176 print 'WARNING: not run: %r' % (func,)
177 WVFAIL('wvtest_main() not called')
181 atexit.register(_check_unfinished)
184 def _run_in_chdir(path, func, *args, **kwargs):
189 sys.path += [path, os.path.split(path)[0]]
190 return func(*args, **kwargs)
196 if sys.version_info >= (2,6,0):
197 _relpath = os.path.relpath;
199 # Implementation for Python 2.5, taken from CPython (tag v2.6,
200 # file Lib/posixpath.py, hg-commit 95fff5a6a276). Update
201 # ./LICENSE When this code is eventually removed.
202 def _relpath(path, start=os.path.curdir):
204 raise ValueError("no path specified")
206 start_list = os.path.abspath(start).split(os.path.sep)
207 path_list = os.path.abspath(path).split(os.path.sep)
209 # Work out how much of the filepath is shared by start and path.
210 i = len(os.path.commonprefix([start_list, path_list]))
212 rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
215 return os.path.join(*rel_list)
218 def _runtest(fname, f):
219 mod = inspect.getmodule(f)
220 relpath = _relpath(mod.__file__, os.getcwd()).replace('.pyc', '.py')
222 print 'Testing "%s" in %s:' % (fname, relpath)
225 _run_in_chdir(os.path.split(mod.__file__)[0], f)
226 except Exception as e:
228 print traceback.format_exc()
229 tb = sys.exc_info()[2]
230 wvtest._result(e, traceback.extract_tb(tb)[1], 'EXCEPTION')
233 def _run_registered_tests():
234 import wvtest as _wvtestmod
235 while _wvtestmod._registered:
236 t = _wvtestmod._registered.pop(0)
237 _runtest(t.func_name, t)
241 def wvtest_main(extra_testfiles=tuple()):
242 import wvtest as _wvtestmod
243 _run_registered_tests()
244 for modname in extra_testfiles:
245 if not os.path.exists(modname):
246 print 'Skipping: %s' % modname
248 if modname.endswith('.py'):
249 modname = modname[:-3]
250 print 'Importing: %s' % modname
251 path, mod = os.path.split(os.path.abspath(modname))
252 nicename = modname.replace(os.path.sep, '.')
253 while nicename.startswith('.'):
254 nicename = modname[1:]
255 _run_in_chdir(path, __import__, nicename, None, None, [])
256 _run_registered_tests()
258 print 'WvTest: %d tests, %d failures.' % (_wvtestmod._tests,
262 if __name__ == '__main__':
263 import wvtest as _wvtestmod
264 sys.modules['wvtest'] = _wvtestmod
265 sys.modules['wvtest.wvtest'] = _wvtestmod
267 wvtest_main(sys.argv[1:])