#!/usr/bin/env python from __future__ import division, print_function, unicode_literals ''' run_tests.py - Run Radiance test suite 2013 - 2018 Georg Mischler Invocation: As script, call with -H for instructions. As module, see docstrings in class RadianceTests for instructions. ''' from __future__ import division, print_function, unicode_literals __all__ = ['TESTCATS', 'RadianceTests', 'main'] import os import sys import types import argparse import unittest SHORTPROGN = os.path.splitext(os.path.basename(sys.argv[0]))[0] TESTCATS = ('pyrad','cal','cv','gen','hd','meta','ot','px', 'rt','util',) class Error(Exception): pass class RadianceTests(): '''Test Radiance programs below subdirectory "testcases" recursively. This class will create a virtual module "testsupport" with constants and functions for use in individual test cases. bindir - list of paths added to PATH path - complete list of paths currently in PATH radlib - list of paths added to RAYPATH raypath - complete list of paths currently in RAYPATH pyradlib - absolute path of python support library directory datadir - absolute path of test data directory datafile([sub, [sub,]] fn) - return absolute file path in data directory or in a subdirectory ''' def __init__(self, **args): '''Args are: bindir=[directory ...] - will be prepended to PATH for tests radlib=[directory ...] - will be prepended to RAYPATH for tests cat=[category ...] - only test those categories (else TESTCATS) V=False - if True, verbose listing of executed tests ''' self.bindir = args.get('bindir') self.radlib = args.get('radlib') self.testcats = args.get('cat') self.V = 2 if args.get('V') else 1 try: old_osenv = os.environ thisfile = os.path.abspath(__file__) self.thisdir = os.path.split(thisfile)[0] self.testdir = os.path.join(self.thisdir, 'testcases') old_syspath = sys.path if self.testdir not in sys.path: sys.path.insert(0, self.testdir) oldpath = old_osenv.get('PATH', '') pathlist = oldpath.split(os.pathsep) if self.bindir: for bdir in self.bindir: if bdir not in pathlist: pathlist.insert(0, bdir) os.environ['PATH'] = os.pathsep.join(pathlist) oldraypath = old_osenv.get('RAYPATH', '') raypathlist = oldraypath.split(os.pathsep) if self.radlib: for rlib in self.radlib + ['.']: if rlib not in raypathlist: raypathlist.insert(0, rlib) os.environ['RAYPATH'] = os.pathsep.join(raypathlist) pyradlib = None for rp in raypathlist: prd = os.path.join(rp, 'pyradlib') if os.path.isdir(prd) or os.path.islink(prd): if rp not in sys.path: sys.path.insert(0, rp) pyradlib = prd if not pyradlib: raise Error('Python support library directory "pyradlib" not found on RAYPATH') # Since this here is the best place to figure out where # everything is, we create an ad-hoc module to hold directory # paths and functions for creating file paths. # The individual test cases can then "import testsupport" to # get access to the complete information. supmod = types.ModuleType(str('testsupport')) datadir = os.path.join(self.thisdir, 'test data') supmod.bindir = self.bindir supmod.datadir = datadir supmod.datafile = lambda fn,*ffn: os.path.join(datadir, fn, *ffn) supmod.path = pathlist supmod.radlib = self.radlib supmod.raypath = raypathlist supmod.pyradlib = pyradlib sys.modules['testsupport'] = supmod self._run_all() finally: if hasattr(sys.modules, 'testsupport'): del sys.modules['testsupport'] os.environ = old_osenv sys.path = old_syspath def _run_all(self): runner = unittest.TextTestRunner(verbosity=self.V) if self.testcats: cats = self.testcats else: cats = TESTCATS for dir in cats: loader = unittest.defaultTestLoader fulldir = os.path.join(self.testdir, dir) if not os.path.isdir(fulldir): raise Error('No such directory: "%s"' % fulldir) suite = loader.discover(fulldir, 'test_*.py', top_level_dir=self.thisdir) count = suite.countTestCases() if count: print('\n--', dir, '----', file=sys.stderr) runner.run(suite) def main(): '''Main function for invocation as script. See usage instructions with -H''' parser = argparse.ArgumentParser(add_help=False, description='Run Radiance test suite',) parser.add_argument('-V', action='store_true', help='Verbose: Print all executed test cases to stderr') parser.add_argument('-H', action='help', help='Help: print this text to stderr and exit') parser.add_argument('-p', action='store', nargs=1, dest='bindir', metavar='bindir', help='Path to Radiance binaries') parser.add_argument('-l', action='store', nargs=1, dest='radlib', metavar='radlib', help='Path to Radiance library') parser.add_argument('-c', action='store', nargs=1, dest='cat', metavar='cat', help='Category of tests to run (else all)') args = parser.parse_args() RadianceTests(**vars(args)) if __name__ == '__main__': try: main() except KeyboardInterrupt: sys.stderr.write('*cancelled*\n') exit(1) except Error as e: sys.stderr.write('%s: %s\n' % (SHORTPROGN, str(e))) exit(-1) # vi: set ts=4 sw=4 :