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())
147 def wvfailure_count():
150 def _check_unfinished():
152 for func in _registered:
153 print 'WARNING: not run: %r' % (func,)
154 WVFAIL('wvtest_main() not called')
158 atexit.register(_check_unfinished)
161 def _run_in_chdir(path, func, *args, **kwargs):
166 sys.path += [path, os.path.split(path)[0]]
167 return func(*args, **kwargs)
173 if sys.version_info >= (2,6,0):
174 _relpath = os.path.relpath;
176 # Implementation for Python 2.5, taken from CPython (tag v2.6,
177 # file Lib/posixpath.py, hg-commit 95fff5a6a276). Update
178 # ./LICENSE When this code is eventually removed.
179 def _relpath(path, start=os.path.curdir):
181 raise ValueError("no path specified")
183 start_list = os.path.abspath(start).split(os.path.sep)
184 path_list = os.path.abspath(path).split(os.path.sep)
186 # Work out how much of the filepath is shared by start and path.
187 i = len(os.path.commonprefix([start_list, path_list]))
189 rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
192 return os.path.join(*rel_list)
195 def _runtest(fname, f):
196 mod = inspect.getmodule(f)
197 relpath = _relpath(mod.__file__, os.getcwd()).replace('.pyc', '.py')
199 print 'Testing "%s" in %s:' % (fname, relpath)
202 _run_in_chdir(os.path.split(mod.__file__)[0], f)
203 except Exception as e:
205 print traceback.format_exc()
206 tb = sys.exc_info()[2]
207 wvtest._result(e, traceback.extract_tb(tb)[1], 'EXCEPTION')
210 def _run_registered_tests():
211 import wvtest as _wvtestmod
212 while _wvtestmod._registered:
213 t = _wvtestmod._registered.pop(0)
214 _runtest(t.func_name, t)
218 def wvtest_main(extra_testfiles=tuple()):
219 import wvtest as _wvtestmod
220 _run_registered_tests()
221 for modname in extra_testfiles:
222 if not os.path.exists(modname):
223 print 'Skipping: %s' % modname
225 if modname.endswith('.py'):
226 modname = modname[:-3]
227 print 'Importing: %s' % modname
228 path, mod = os.path.split(os.path.abspath(modname))
229 nicename = modname.replace(os.path.sep, '.')
230 while nicename.startswith('.'):
231 nicename = modname[1:]
232 _run_in_chdir(path, __import__, nicename, None, None, [])
233 _run_registered_tests()
235 print 'WvTest: %d tests, %d failures.' % (_wvtestmod._tests,
239 if __name__ == '__main__':
240 import wvtest as _wvtestmod
241 sys.modules['wvtest'] = _wvtestmod
242 sys.modules['wvtest.wvtest'] = _wvtestmod
244 wvtest_main(sys.argv[1:])