1# _________________________________________________________________________ 2# 3# PyUtilib: A Python utility library. 4# Copyright (c) 2008 Sandia Corporation. 5# This software is distributed under the BSD License. 6# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, 7# the U.S. Government retains certain rights in this software. 8# _________________________________________________________________________ 9 10import sys 11try: 12 import nose 13 import nose.plugins 14except ImportError: 15 print("This testing utility requires the 'nose' Python testing tool") 16 sys.exit(1) 17try: 18 import nosexunit 19 import nosexunit.plugin 20 nose_xunit_installed = True 21except ImportError: 22 nose_xunit_installed = False 23try: 24 import coverage 25 import nose.plugins.cover 26 coverage_installed = True 27except ImportError: 28 coverage_installed = False 29 30import re 31import logging 32import os 33import os.path 34import glob 35import copy 36from optparse import OptionParser 37 38# Ignore exceptions that occur during a logging statement 39logging.raiseExceptions = 0 40 41 42class UnwantedPackagePlugin(nose.plugins.Plugin): 43 enabled = True 44 name = "unwanted-package" 45 46 def __init__(self, unwanted): 47 self.unwanted = unwanted 48 49 def configure(self, options, conf): 50 pass 51 52 def wantDirectory(self, dirname): 53 want = None 54 if os.path.basename(dirname) in self.unwanted: 55 want = False 56 return want 57 58 59def generate_options(package, packages, subpackages, filter, options, testdir, 60 xunitdir, dirname): 61 if not type(packages) is list: 62 tmp = [packages] 63 else: 64 tmp = packages 65 newargs = [] 66 if options.xunit: 67 newargs = ['--with-xunit', '--xunit-file', xunitdir + os.sep + 'TEST-' + 68 package + '.xml'] 69 #if coverage_installed: 70 #newargs = newargs + ['--source-folder', '.'] 71 if coverage_installed: 72 newargs = newargs + ['--with-coverage', '--cover-erase', 73 '--cover-inclusive', '--cover-package', package] 74 if options.filtering or options.filtering_all: 75 for item in filter: 76 newargs.append('--cover-filter=' + item) 77 if len(tmp) > 0: 78 for item in subpackages: 79 if not item in tmp: 80 newargs.append('--cover-filter=' + package + '.' + item) 81 if options.verbose: 82 newargs = newargs + ['--verbosity=3'] 83 newargs = newargs + ['--where', dirname] 84 return newargs 85 86 87def main(argv, package, subpackages, filter, testdir, dirname="test"): 88 89 parser = OptionParser() 90 parser.add_option( 91 "--no-xunit", 92 help="Disable generation of XUnit XML summary", 93 action="store_false", 94 dest="xunit", 95 default=True) 96 parser.add_option( 97 "-v", 98 "--verbose", 99 help="Provide verbose output", 100 action="store_true", 101 dest="verbose", 102 default=False) 103 parser.add_option( 104 "-f", 105 "--filter", 106 help="Enable filtering of coverage tests with a customized nose installation", 107 action="store_true", 108 dest="filtering", 109 default=False) 110 parser.add_option( 111 "-F", 112 "--filter-all", 113 help="Apply nose to all packages, filtering each coverage test", 114 action="store_true", 115 dest="filtering_all", 116 default=False) 117 parser.usage = "runtests [options] <package> [...]" 118 parser.description = "A utility to run Pyomo tests. A particular feature of this tool is the ability to filter coverage information, using a customized installation of the nose utility." 119 parser.epilog = """The customized nose utility that supports filtering can be obtained from Bill Hart (wehart@sandia.gov).""" 120 # 121 # Process argv list 122 # 123 (options, args) = parser.parse_args(args=argv) 124 # 125 # Preprocess arguments, to eliminate trailing '/' or '\\' characters, which a user 126 # might add using tab completion. 127 # 128 for i in range(0, len(args)): 129 if args[i][-1] == os.sep: 130 args[i] = args[i][:-1] 131 # 132 # Verify that the arguments are valid subpackages 133 # 134 unwanted = copy.copy(subpackages) 135 for arg in args[1:]: 136 if not arg in subpackages: 137 print("ERROR: no subpackage '" + arg) 138 sys.exit(1) 139 unwanted.remove(arg) 140 if unwanted == subpackages: 141 unwanted = [] 142 # 143 # Remove coverage files from previous 'runtests' executions 144 # 145 coverage_file = testdir + os.sep + dirname + os.sep + ".coverage" 146 if os.path.exists(coverage_file): 147 os.remove(coverage_file) 148 os.environ["COVERAGE_FILE"] = coverage_file 149 #for file in glob.glob("*/.coverage"): 150 #os.remove(file) 151 #for file in glob.glob("*/*/.coverage"): 152 #os.remove(file) 153 # 154 # Remove XML files from previous 'runtests' executions 155 # 156 xunitdir = testdir + os.sep + dirname + os.sep + "xunit" 157 if os.path.exists(xunitdir): 158 for file in glob.glob(xunitdir + os.sep + "TEST*.xml"): 159 os.remove(file) 160 else: 161 os.mkdir(xunitdir) 162 163 plugins = [UnwantedPackagePlugin(unwanted)] 164 #if nose_xunit_installed and options.xunit: 165 #plugins.append(nosexunit.plugin.NoseXUnit()) 166 #if coverage_installed: 167 #plugins.append(nose.plugins.cover.Coverage()) 168 #plugins.append(nose.plugins.xunit.Xunit()) 169 if not options.filtering_all: 170 newargs = ['runtests'] + generate_options( 171 package, args[1:], subpackages, filter, options, testdir, xunitdir, 172 dirname) + args[1:] 173 os.chdir(testdir) 174 if options.verbose: 175 print("Nose Arguments:", newargs) 176 print("Test Dir:", testdir) 177 if len(args) > 1: 178 print("Test Packages:",) 179 for arg in args[1:]: 180 print(arg,) 181 print("") 182 if len(unwanted) > 1: 183 print("Ignored Packages:", unwanted) 184 sys.argv = newargs 185 nose.run(argv=newargs, addplugins=plugins) 186 else: 187 if len(args[1:]) == 0: 188 arglist = subpackages 189 else: 190 arglist = args[1:] 191 for arg in arglist: 192 newargs = ['runtests'] + generate_options(arg, options) + [arg] 193 print("Package Coverage Tests: " + arg) 194 tmp = sys.stdout 195 os.chdir(testdir) 196 if options.verbose: 197 print("Nose Arguments:", newargs) 198 print("Test Dir:", testdir) 199 if len(args) > 1: 200 print("Test Packages:",) 201 for arg in args[1:]: 202 print(arg,) 203 print("") 204 if len(unwanted) > 1: 205 print("Ignored Packages:", unwanted) 206 nose.run(argv=newargs, addplugins=plugins) 207 sys.stdout = tmp 208 # 209 # Rename xUnit files and insert the package information 210 # 211 if os.path.exists(xunitdir): 212 p = re.compile('^.*TEST-(.+)\.xml') 213 for file in glob.glob(xunitdir + os.sep + "TEST-*.xml"): 214 oldname = p.match(file).group(1) 215 if oldname == "test": 216 suffix = "" 217 else: 218 suffix = "." + oldname 219 220 FILE = open(file, "r") 221 text0 = "".join(FILE.readlines()) 222 FILE.close() 223 ptmp = re.compile("testsuite name=\"nosetests\"") 224 text1 = ptmp.sub("testsuite name=\"" + package + "\"", text0) 225 #ptmp = re.compile("classname=\""+oldname) 226 #text2 = ptmp.sub("classname=\""+package+suffix, text1) 227 #FILE = open(xunitdir+os.sep+"TEST-"+package+suffix+".xml","w") 228 FILE = open(file, "w") 229 FILE.write(text1) 230 FILE.close() 231 #os.remove(file) 232