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 _code_rx = re.compile(r'^\w+\((.*)\)(\s*#.*)?$')
91 text = _caller_stack(2)[3]
92 return _code_rx.sub(r'\1', text)
95 filename = _caller_stack(1)[0]
96 sys.stderr.write('Testing \"' + message + '\" in ' + filename + ':\n')
99 ''' Issues a notification. '''
100 return _result(message, _caller_stack(1), 'ok')
102 def WVPASS(cond = True):
103 ''' Counts a test failure unless cond is true. '''
104 return _check(cond, _code())
106 def WVFAIL(cond = True):
107 ''' Counts a test failure unless cond is false. '''
108 return _check(not cond, 'NOT(%s)' % _code())
111 ''' Counts a test failure unless a == b. '''
112 return _check(a == b, '%s == %s' % (repr(a), repr(b)))
115 ''' Counts a test failure unless a != b. '''
116 return _check(a != b, '%s != %s' % (repr(a), repr(b)))
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)))
134 def WVEXCEPT(etype, func, *args, **kwargs):
135 ''' Counts a test failure unless func throws an 'etype' exception.
136 You have to spell out the function name and arguments, rather than
137 calling the function yourself, so that WVEXCEPT can run before
138 your test code throws an exception.
141 func(*args, **kwargs)
143 return _check(True, 'EXCEPT(%s)' % _code())
145 _check(False, 'EXCEPT(%s)' % _code())
148 return _check(False, 'EXCEPT(%s)' % _code())
162 def wvfailure_count():
165 def _check_unfinished():
167 for func in _registered:
168 print 'WARNING: not run: %r' % (func,)
169 WVFAIL('wvtest_main() not called')
173 atexit.register(_check_unfinished)
176 def _run_in_chdir(path, func, *args, **kwargs):
181 sys.path += [path, os.path.split(path)[0]]
182 return func(*args, **kwargs)
188 if sys.version_info >= (2,6,0):
189 _relpath = os.path.relpath;
191 # Implementation for Python 2.5, taken from CPython (tag v2.6,
192 # file Lib/posixpath.py, hg-commit 95fff5a6a276). Update
193 # ./LICENSE When this code is eventually removed.
194 def _relpath(path, start=os.path.curdir):
196 raise ValueError("no path specified")
198 start_list = os.path.abspath(start).split(os.path.sep)
199 path_list = os.path.abspath(path).split(os.path.sep)
201 # Work out how much of the filepath is shared by start and path.
202 i = len(os.path.commonprefix([start_list, path_list]))
204 rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
207 return os.path.join(*rel_list)
210 def _runtest(fname, f):
211 mod = inspect.getmodule(f)
212 relpath = _relpath(mod.__file__, os.getcwd()).replace('.pyc', '.py')
214 print 'Testing "%s" in %s:' % (fname, relpath)
217 _run_in_chdir(os.path.split(mod.__file__)[0], f)
218 except Exception as e:
220 print traceback.format_exc()
221 tb = sys.exc_info()[2]
222 wvtest._result(e, traceback.extract_tb(tb)[1], 'EXCEPTION')
225 def _run_registered_tests():
226 import wvtest as _wvtestmod
227 while _wvtestmod._registered:
228 t = _wvtestmod._registered.pop(0)
229 _runtest(t.func_name, t)
233 def wvtest_main(extra_testfiles=tuple()):
234 import wvtest as _wvtestmod
235 _run_registered_tests()
236 for modname in extra_testfiles:
237 if not os.path.exists(modname):
238 print 'Skipping: %s' % modname
240 if modname.endswith('.py'):
241 modname = modname[:-3]
242 print 'Importing: %s' % modname
243 path, mod = os.path.split(os.path.abspath(modname))
244 nicename = modname.replace(os.path.sep, '.')
245 while nicename.startswith('.'):
246 nicename = modname[1:]
247 _run_in_chdir(path, __import__, nicename, None, None, [])
248 _run_registered_tests()
250 print 'WvTest: %d tests, %d failures.' % (_wvtestmod._tests,
254 if __name__ == '__main__':
255 import wvtest as _wvtestmod
256 sys.modules['wvtest'] = _wvtestmod
257 sys.modules['wvtest.wvtest'] = _wvtestmod
259 wvtest_main(sys.argv[1:])