From 2d867d814f91ae7ccd66611feb90a15e8d9f50e9 Mon Sep 17 00:00:00 2001 From: Avery Pennarun Date: Wed, 30 Dec 2009 15:41:51 -0500 Subject: [PATCH] Merge wvtest.py and wvtestmain.py into one file. This makes it a bit easier to bring into your own projects, since it's just a single file. Copied from eqldata project, commit 3b004336b117c01885f09f95b6e2aededd2de377. --- README | 4 +- python/Makefile | 2 +- python/t/__init__.py | 0 python/wvtest.py | 199 ++++++++++++++++++++++++++----------------- python/wvtestmain.py | 36 -------- 5 files changed, 126 insertions(+), 115 deletions(-) create mode 100644 python/t/__init__.py mode change 100644 => 100755 python/wvtest.py delete mode 100755 python/wvtestmain.py diff --git a/README b/README index 4f6aab1..ba1837d 100644 --- a/README +++ b/README @@ -172,7 +172,7 @@ WvTest provides a simple perl script called wvtestrun, which runs a test program and parses its output. It works like this: cd python - ../wvtestrun python ./wvtestmain.py t/twvtest.py + ../wvtestrun ./wvtest.py t/twvtest.py (Why can't we just pipe the output to wvtestrun, instead of having wvtestrun run the test program? Three reasons: first, a @@ -298,7 +298,7 @@ With python, since there's no linker, you have to just tell it which files to run: cd python - ../wvtestrun ./wvtestmain.py ...filenames... + ../wvtestrun ./wvtest.py ...filenames... What else can parse WvTest output? diff --git a/python/Makefile b/python/Makefile index febdb3a..e9e23f2 100644 --- a/python/Makefile +++ b/python/Makefile @@ -4,7 +4,7 @@ all: @false runtests: - python wvtestmain.py \ + ./wvtest.py \ $(patsubst ./%t,%t/*.py,$(shell find -type d -name t)) test: diff --git a/python/t/__init__.py b/python/t/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python/wvtest.py b/python/wvtest.py old mode 100644 new mode 100755 index 6512234..a5d1930 --- a/python/wvtest.py +++ b/python/wvtest.py @@ -1,84 +1,131 @@ -# -# WvTest: -# Copyright (C)2009 EQL Data Inc. and contributors. -# Licensed under the GNU Library General Public License, version 2. -# See the included file named LICENSE for license information. -# +#!/usr/bin/env python import traceback -import os.path +import os import re import sys -_registered = [] -_tests = 0 -_fails = 0 - -def wvtest(func): - ''' Use this decorator (@wvtest) in front of any function you want to run - as part of the unit test suite. Then run: - python wvtestmain.py path/to/yourtest.py - to run all the @wvtest functions in that file. - ''' - _registered.append(func) - return func - -def _result(msg, tb, code): - global _tests, _fails - _tests += 1 - if code != 'ok': - _fails += 1 - (filename, line, func, text) = tb - filename = os.path.basename(filename) - msg = re.sub(r'\s+', ' ', str(msg)) - sys.stderr.flush() - print '! %-70s %s' % ('%s:%-4d %s' % (filename, line, msg), - code) - sys.stdout.flush() +if __name__ != "__main__": # we're imported as a module + _registered = [] + _tests = 0 + _fails = 0 + def wvtest(func): + """ Use this decorator (@wvtest) in front of any function you want to run + as part of the unit test suite. Then run: + python wvtest.py path/to/yourtest.py + to run all the @wvtest functions in that file. + """ + _registered.append(func) + return func + + + def _result(msg, tb, code): + global _tests, _fails + _tests += 1 + if code != 'ok': + _fails += 1 + (filename, line, func, text) = tb + filename = os.path.basename(filename) + msg = re.sub(r'\s+', ' ', str(msg)) + sys.stderr.flush() + print '! %-70s %s' % ('%s:%-4d %s' % (filename, line, msg), + code) + sys.stdout.flush() + + + def _check(cond, msg = 'unknown', tb = None): + if tb == None: tb = traceback.extract_stack()[-3] + if cond: + _result(msg, tb, 'ok') + else: + _result(msg, tb, 'FAILED') + return cond + + + def _code(): + (filename, line, func, text) = traceback.extract_stack()[-3] + text = re.sub(r'^\w+\((.*)\)$', r'\1', text); + return text + + + def WVPASS(cond = True): + ''' Throws an exception unless cond is true. ''' + return _check(cond, _code()) + + def WVFAIL(cond = True): + ''' Throws an exception unless cond is false. ''' + return _check(not cond, 'NOT(%s)' % _code()) + + def WVPASSEQ(a, b): + ''' Throws an exception unless a == b. ''' + return _check(a == b, '%s == %s' % (repr(a), repr(b))) + + def WVPASSNE(a, b): + ''' Throws an exception unless a != b. ''' + return _check(a != b, '%s != %s' % (repr(a), repr(b))) + + def WVPASSLT(a, b): + ''' Throws an exception unless a < b. ''' + return _check(a < b, '%s < %s' % (repr(a), repr(b))) + + def WVPASSLE(a, b): + ''' Throws an exception unless a <= b. ''' + return _check(a <= b, '%s <= %s' % (repr(a), repr(b))) + + def WVPASSGT(a, b): + ''' Throws an exception unless a > b. ''' + return _check(a > b, '%s > %s' % (repr(a), repr(b))) + + def WVPASSGE(a, b): + ''' Throws an exception unless a >= b. ''' + return _check(a >= b, '%s >= %s' % (repr(a), repr(b))) -def _check(cond, msg = 'unknown', tb = None): - if tb == None: tb = traceback.extract_stack()[-3] - if cond: - _result(msg, tb, 'ok') - else: - _result(msg, tb, 'FAILED') - return cond - -def _code(): - (filename, line, func, text) = traceback.extract_stack()[-3] - text = re.sub(r'^\w+\((.*)\)$', r'\1', text); - return text - -def WVPASS(cond = True): - ''' Throws an exception unless cond is true. ''' - return _check(cond, _code()) - -def WVFAIL(cond = True): - ''' Throws an exception unless cond is false. ''' - return _check(not cond, 'NOT(%s)' % _code()) - -def WVPASSEQ(a, b): - ''' Throws an exception unless a == b. ''' - return _check(a == b, '%s == %s' % (repr(a), repr(b))) - -def WVPASSNE(a, b): - ''' Throws an exception unless a != b. ''' - return _check(a != b, '%s != %s' % (repr(a), repr(b))) - -def WVPASSLT(a, b): - ''' Throws an exception unless a < b. ''' - return _check(a < b, '%s < %s' % (repr(a), repr(b))) - -def WVPASSLE(a, b): - ''' Throws an exception unless a <= b. ''' - return _check(a <= b, '%s <= %s' % (repr(a), repr(b))) - -def WVPASSGT(a, b): - ''' Throws an exception unless a > b. ''' - return _check(a > b, '%s > %s' % (repr(a), repr(b))) - -def WVPASSGE(a, b): - ''' Throws an exception unless a >= b. ''' - return _check(a >= b, '%s >= %s' % (repr(a), repr(b))) +else: # we're the main program + # NOTE + # Why do we do this in such convoluted way? Because if you run + # wvtest.py as a main program and it imports your test files, then + # those test files will try to import the wvtest module recursively. + # That actually *works* fine, because we don't run this main program + # when we're imported as a module. But you end up with two separate + # wvtest modules, the one that gets imported, and the one that's the + # main program. Each of them would have duplicated global variables + # (most importantly, wvtest._registered), and so screwy things could + # happen. Thus, we make the main program module *totally* different + # from the imported module. Then we import wvtest (the module) into + # wvtest (the main program) here and make sure to refer to the right + # versions of global variables. + # + # All this is done just so that wvtest.py can be a single file that's + # easy to import into your own applications. + import wvtest + + def _runtest(modname, fname, f): + print + print 'Testing "%s" in %s.py:' % (fname, modname) + sys.stdout.flush() + try: + f() + except Exception, e: + print + print traceback.format_exc() + tb = sys.exc_info()[2] + wvtest._result(e, traceback.extract_tb(tb)[-1], + 'EXCEPTION') + + # main code + for modname in sys.argv[1:]: + if not os.path.exists(modname): + print 'Skipping: %s' % modname + continue + if modname.endswith('.py'): + modname = modname[:-3] + print 'Importing: %s' % modname + wvtest._registered = [] + mod = __import__(modname.replace('/', '.'), None, None, []) + for t in wvtest._registered: + _runtest(modname, t.func_name, t) + print + print + print 'WvTest: %d tests, %d failures.' % (wvtest._tests, wvtest._fails) diff --git a/python/wvtestmain.py b/python/wvtestmain.py deleted file mode 100755 index e975245..0000000 --- a/python/wvtestmain.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/python -# -# WvTest: -# Copyright (C)2009 EQL Data Inc. and contributors. -# Licensed under the GNU Library General Public License, version 2. -# See the included file named LICENSE for license information. -# -import wvtest -import sys, imp, types, os, os.path -import traceback - -def runtest(modname, fname, f): - print - print 'Testing "%s" in %s.py:' % (fname, modname) - try: - f() - except Exception, e: - print - print traceback.format_exc() - tb = sys.exc_info()[2] - wvtest._result(e, traceback.extract_tb(tb)[-1], - 'EXCEPTION') - -for modname in sys.argv[1:]: - if modname.endswith('.py'): - modname = modname[:-3] - print - print 'Importing: %s' % modname - wvtest._registered = [] - mod = __import__(modname, None, None, []) - - for t in wvtest._registered: - runtest(modname, t.func_name, t) - -print -print 'WvTest: %d tests, %d failures.' % (wvtest._tests, wvtest._fails) -- 2.39.2