| 1 | schorsch | 1.3 | #!/usr/bin/env python | 
| 2 |  |  | # -*- coding: utf-8 -*- | 
| 3 |  |  | ''' run_tests.py - Run Radiance test suite | 
| 4 |  |  | 2013 - 2016 Georg Mischler | 
| 5 |  |  |  | 
| 6 |  |  | Invocation: | 
| 7 |  |  | As script, call with -H for instructions. | 
| 8 |  |  | As module, see docstrings in class RadianceTests for instructions. | 
| 9 |  |  | ''' | 
| 10 |  |  | from __future__ import division, print_function, unicode_literals | 
| 11 |  |  | __all__ = ['TESTCATS', 'RadianceTests', 'main'] | 
| 12 |  |  | import os | 
| 13 |  |  | import sys | 
| 14 |  |  | import types | 
| 15 |  |  | import argparse | 
| 16 |  |  | import unittest | 
| 17 |  |  |  | 
| 18 |  |  | SHORTPROGN = os.path.splitext(os.path.basename(sys.argv[0]))[0] | 
| 19 |  |  | TESTCATS = ('cal','cv','gen','hd','meta','ot','px', 'rt','util',) | 
| 20 |  |  |  | 
| 21 |  |  | class Error(Exception): pass | 
| 22 |  |  |  | 
| 23 |  |  | class RadianceTests(): | 
| 24 |  |  | '''Test Radiance programs below subdirectory "testcases" recursively. | 
| 25 |  |  |  | 
| 26 |  |  | This class will create a virtual module "testsupport" with constants | 
| 27 |  |  | and functions for use in individual test cases. | 
| 28 |  |  |  | 
| 29 |  |  | testsupport.bindir   - list of paths added to PATH | 
| 30 |  |  | testsupport.path     - complete list of paths currently in PATH | 
| 31 |  |  | testsupport.radlib   - list of paths added to RAYPATH | 
| 32 |  |  | testsupport.raypath  - complete list of paths currently in RAYPATH | 
| 33 |  |  | testsupport.pyradlib - absolute path of python support library directory | 
| 34 |  |  | testsupport.datadir  - absolute path of test data directory | 
| 35 |  |  | testsupport.datafile([sub, [sub,]] fn) - return absolute file path in | 
| 36 |  |  | data directory or in a subdirectory | 
| 37 |  |  | ''' | 
| 38 |  |  | def __init__(self, **args): | 
| 39 |  |  | '''Args are: | 
| 40 |  |  | bindir=[directory ...] - will be prepended to PATH for tests | 
| 41 |  |  | radlib=[directory ...] - will be prepended to RAYPATH for tests | 
| 42 |  |  | cat=[category ...]     - only test those categories (else TESTCATS) | 
| 43 |  |  | V=False                - if True, verbose listing of executed tests | 
| 44 |  |  | ''' | 
| 45 |  |  | self.bindir = args.get('bindir') | 
| 46 |  |  | self.radlib = args.get('radlib') | 
| 47 |  |  | self.testcats = args.get('cat') | 
| 48 |  |  | self.V = 2 if args.get('V') else 1 | 
| 49 |  |  | try: | 
| 50 |  |  | old_osenv = os.environ | 
| 51 | schorsch | 1.1 |  | 
| 52 | schorsch | 1.3 | thisfile = os.path.abspath(__file__) | 
| 53 |  |  | self.thisdir = os.path.split(thisfile)[0] | 
| 54 |  |  | self.testdir = os.path.join(self.thisdir, 'testcases') | 
| 55 |  |  | old_syspath = sys.path | 
| 56 |  |  | if self.testdir not in sys.path: | 
| 57 |  |  | sys.path.insert(0, self.testdir) | 
| 58 |  |  |  | 
| 59 |  |  | oldpath = old_osenv.get('PATH', '') | 
| 60 |  |  | pathlist = oldpath.split(os.pathsep) | 
| 61 |  |  | if self.bindir: | 
| 62 |  |  | for bdir in self.bindir: | 
| 63 |  |  | if bdir not in pathlist: | 
| 64 |  |  | pathlist.insert(0, bdir) | 
| 65 |  |  | os.environ['PATH'] = os.pathsep.join(pathlist) | 
| 66 |  |  |  | 
| 67 |  |  | oldraypath = old_osenv.get('RAYPATH', '') | 
| 68 |  |  | raypathlist = oldraypath.split(os.pathsep) | 
| 69 |  |  | if self.radlib: | 
| 70 |  |  | for rlib in self.radlib: | 
| 71 |  |  | if rlib not in raypathlist: | 
| 72 |  |  | raypathlist.insert(0, rlib) | 
| 73 |  |  | os.environ['RAYPATH'] = os.pathsep.join(raypathlist) | 
| 74 |  |  |  | 
| 75 |  |  | pyradlib = None | 
| 76 |  |  | for rp in raypathlist: | 
| 77 |  |  | prd = os.path.join(rp, 'pyradlib') | 
| 78 |  |  | #print(prd) | 
| 79 |  |  | if os.path.isdir(prd) or os.path.islink(prd): | 
| 80 |  |  | #print('--- found !!!') | 
| 81 |  |  | if rp not in sys.path: | 
| 82 |  |  | sys.path.insert(0, rp) | 
| 83 |  |  | pyradlib = prd | 
| 84 |  |  | if not pyradlib: | 
| 85 |  |  | raise Error('Python support library directory "pyradlib" not found on RAYPATH') | 
| 86 |  |  |  | 
| 87 |  |  | # Since this here is the best place to figure out where | 
| 88 |  |  | # everything is, we create an ad-hoc module to hold directory | 
| 89 |  |  | # paths and functions for creating file paths. | 
| 90 |  |  | # The individual test cases can then "import testsupport" to | 
| 91 |  |  | # get access to the complete information. | 
| 92 |  |  | supmod = types.ModuleType(str('testsupport')) | 
| 93 |  |  | datadir = os.path.join(self.thisdir, 'test data') | 
| 94 |  |  | supmod.bindir = self.bindir | 
| 95 |  |  | supmod.datadir = datadir | 
| 96 |  |  | supmod.datafile = lambda fn,*ffn: os.path.join(datadir, fn, *ffn) | 
| 97 |  |  | supmod.path = pathlist | 
| 98 |  |  | supmod.radlib = self.radlib | 
| 99 |  |  | supmod.raypath = raypathlist | 
| 100 |  |  | supmod.pyradlib = pyradlib | 
| 101 |  |  | sys.modules['testsupport'] = supmod | 
| 102 |  |  |  | 
| 103 |  |  | self._run_all() | 
| 104 |  |  | finally: | 
| 105 |  |  | if hasattr(sys.modules, 'testsupport'): | 
| 106 |  |  | del sys.modules['testsupport'] | 
| 107 |  |  | os.environ = old_osenv | 
| 108 |  |  | sys.path = old_syspath | 
| 109 |  |  |  | 
| 110 |  |  | def _run_all(self): | 
| 111 |  |  | runner = unittest.TextTestRunner(verbosity=self.V) | 
| 112 |  |  | if self.testcats: | 
| 113 |  |  | cats = self.testcats | 
| 114 |  |  | else: cats = TESTCATS | 
| 115 |  |  | for dir in cats: | 
| 116 |  |  | loader = unittest.defaultTestLoader | 
| 117 |  |  | fulldir = os.path.join(self.testdir, dir) | 
| 118 |  |  | if not os.path.isdir(fulldir): | 
| 119 |  |  | raise Error('No such directory: "%s"' % fulldir) | 
| 120 |  |  | suite = loader.discover(fulldir, 'test*.py', | 
| 121 |  |  | top_level_dir=self.thisdir) | 
| 122 |  |  | count = suite.countTestCases() | 
| 123 |  |  | if count: | 
| 124 |  |  | print('\n--', dir, '----', file=sys.stderr) | 
| 125 |  |  | runner.run(suite) | 
| 126 |  |  |  | 
| 127 |  |  |  | 
| 128 |  |  | def main(): | 
| 129 |  |  | '''Main function for invocation as script. See usage instructions with -H''' | 
| 130 |  |  | parser = argparse.ArgumentParser(add_help=False, | 
| 131 |  |  | description='Run Radiance test suite',) | 
| 132 |  |  | parser.add_argument('-V', action='store_true', | 
| 133 |  |  | help='Verbose: Print all executed test cases to stderr') | 
| 134 |  |  | parser.add_argument('-H', action='help', | 
| 135 |  |  | help='Help: print this text to stderr and exit') | 
| 136 |  |  | parser.add_argument('-p', action='store', nargs=1, | 
| 137 |  |  | dest='bindir', metavar='bindir', help='Path to Radiance binaries') | 
| 138 |  |  | parser.add_argument('-l', action='store', nargs=1, | 
| 139 |  |  | dest='radlib', metavar='radlib', help='Path to Radiance library') | 
| 140 |  |  | parser.add_argument('-c', action='store', nargs=1, | 
| 141 |  |  | dest='cat', metavar='cat', help='Category of tests to run (else all)') | 
| 142 |  |  | args = parser.parse_args() | 
| 143 |  |  | RadianceTests(**vars(args)) | 
| 144 | schorsch | 1.1 |  | 
| 145 |  |  |  | 
| 146 |  |  | if __name__ == '__main__': | 
| 147 | schorsch | 1.3 | try: main() | 
| 148 |  |  | except KeyboardInterrupt: | 
| 149 |  |  | sys.stderr.write('*cancelled*\n') | 
| 150 |  |  | exit(1) | 
| 151 |  |  | except Error as e: | 
| 152 |  |  | sys.stderr.write('%s: %s\n' % (SHORTPROGN, str(e))) | 
| 153 |  |  | exit(-1) | 
| 154 | schorsch | 1.1 |  | 
| 155 | schorsch | 1.3 | # vi: set ts=4 sw=4 : |