# _________________________________________________________________________ # # PyUtilib: A Python utility library. # Copyright (c) 2008 Sandia Corporation. # This software is distributed under the BSD License. # Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, # the U.S. Government retains certain rights in this software. # _________________________________________________________________________ import sys try: import nose import nose.plugins except ImportError: print("This testing utility requires the 'nose' Python testing tool") sys.exit(1) try: import nosexunit import nosexunit.plugin nose_xunit_installed = True except ImportError: nose_xunit_installed = False try: import coverage import nose.plugins.cover coverage_installed = True except ImportError: coverage_installed = False import re import logging import os import os.path import glob import copy from optparse import OptionParser # Ignore exceptions that occur during a logging statement logging.raiseExceptions = 0 class UnwantedPackagePlugin(nose.plugins.Plugin): enabled = True name = "unwanted-package" def __init__(self, unwanted): self.unwanted = unwanted def configure(self, options, conf): pass def wantDirectory(self, dirname): want = None if os.path.basename(dirname) in self.unwanted: want = False return want def generate_options(package, packages, subpackages, filter, options, testdir, xunitdir, dirname): if not type(packages) is list: tmp = [packages] else: tmp = packages newargs = [] if options.xunit: newargs = ['--with-xunit', '--xunit-file', xunitdir + os.sep + 'TEST-' + package + '.xml'] #if coverage_installed: #newargs = newargs + ['--source-folder', '.'] if coverage_installed: newargs = newargs + ['--with-coverage', '--cover-erase', '--cover-inclusive', '--cover-package', package] if options.filtering or options.filtering_all: for item in filter: newargs.append('--cover-filter=' + item) if len(tmp) > 0: for item in subpackages: if not item in tmp: newargs.append('--cover-filter=' + package + '.' + item) if options.verbose: newargs = newargs + ['--verbosity=3'] newargs = newargs + ['--where', dirname] return newargs def main(argv, package, subpackages, filter, testdir, dirname="test"): parser = OptionParser() parser.add_option( "--no-xunit", help="Disable generation of XUnit XML summary", action="store_false", dest="xunit", default=True) parser.add_option( "-v", "--verbose", help="Provide verbose output", action="store_true", dest="verbose", default=False) parser.add_option( "-f", "--filter", help="Enable filtering of coverage tests with a customized nose installation", action="store_true", dest="filtering", default=False) parser.add_option( "-F", "--filter-all", help="Apply nose to all packages, filtering each coverage test", action="store_true", dest="filtering_all", default=False) parser.usage = "runtests [options] [...]" 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." parser.epilog = """The customized nose utility that supports filtering can be obtained from Bill Hart (wehart@sandia.gov).""" # # Process argv list # (options, args) = parser.parse_args(args=argv) # # Preprocess arguments, to eliminate trailing '/' or '\\' characters, which a user # might add using tab completion. # for i in range(0, len(args)): if args[i][-1] == os.sep: args[i] = args[i][:-1] # # Verify that the arguments are valid subpackages # unwanted = copy.copy(subpackages) for arg in args[1:]: if not arg in subpackages: print("ERROR: no subpackage '" + arg) sys.exit(1) unwanted.remove(arg) if unwanted == subpackages: unwanted = [] # # Remove coverage files from previous 'runtests' executions # coverage_file = testdir + os.sep + dirname + os.sep + ".coverage" if os.path.exists(coverage_file): os.remove(coverage_file) os.environ["COVERAGE_FILE"] = coverage_file #for file in glob.glob("*/.coverage"): #os.remove(file) #for file in glob.glob("*/*/.coverage"): #os.remove(file) # # Remove XML files from previous 'runtests' executions # xunitdir = testdir + os.sep + dirname + os.sep + "xunit" if os.path.exists(xunitdir): for file in glob.glob(xunitdir + os.sep + "TEST*.xml"): os.remove(file) else: os.mkdir(xunitdir) plugins = [UnwantedPackagePlugin(unwanted)] #if nose_xunit_installed and options.xunit: #plugins.append(nosexunit.plugin.NoseXUnit()) #if coverage_installed: #plugins.append(nose.plugins.cover.Coverage()) #plugins.append(nose.plugins.xunit.Xunit()) if not options.filtering_all: newargs = ['runtests'] + generate_options( package, args[1:], subpackages, filter, options, testdir, xunitdir, dirname) + args[1:] os.chdir(testdir) if options.verbose: print("Nose Arguments:", newargs) print("Test Dir:", testdir) if len(args) > 1: print("Test Packages:",) for arg in args[1:]: print(arg,) print("") if len(unwanted) > 1: print("Ignored Packages:", unwanted) sys.argv = newargs nose.run(argv=newargs, addplugins=plugins) else: if len(args[1:]) == 0: arglist = subpackages else: arglist = args[1:] for arg in arglist: newargs = ['runtests'] + generate_options(arg, options) + [arg] print("Package Coverage Tests: " + arg) tmp = sys.stdout os.chdir(testdir) if options.verbose: print("Nose Arguments:", newargs) print("Test Dir:", testdir) if len(args) > 1: print("Test Packages:",) for arg in args[1:]: print(arg,) print("") if len(unwanted) > 1: print("Ignored Packages:", unwanted) nose.run(argv=newargs, addplugins=plugins) sys.stdout = tmp # # Rename xUnit files and insert the package information # if os.path.exists(xunitdir): p = re.compile('^.*TEST-(.+)\.xml') for file in glob.glob(xunitdir + os.sep + "TEST-*.xml"): oldname = p.match(file).group(1) if oldname == "test": suffix = "" else: suffix = "." + oldname FILE = open(file, "r") text0 = "".join(FILE.readlines()) FILE.close() ptmp = re.compile("testsuite name=\"nosetests\"") text1 = ptmp.sub("testsuite name=\"" + package + "\"", text0) #ptmp = re.compile("classname=\""+oldname) #text2 = ptmp.sub("classname=\""+package+suffix, text1) #FILE = open(xunitdir+os.sep+"TEST-"+package+suffix+".xml","w") FILE = open(file, "w") FILE.write(text1) FILE.close() #os.remove(file)