From: <de...@us...> - 2004-01-07 02:00:51
|
Update of /cvsroot/pymerase/smw/smw/testdriver In directory sc8-pr-cvs1:/tmp/cvs-serv32238/smw/testdriver Added Files: DiagramEditorTester.py PropertyEditorTester.py __init__.py pycov.py unittester.py Log Message: Imported version of SMW downloaded on 2003 Apr 14 --- NEW FILE: DiagramEditorTester.py --- import unittest import sys from smw.metamodel.MetaMM import * from smw.modeler import modelerApp from smw.modeler.DiagramEditor import * from smw.modeler.UML.UMLCoreEditor import * import smw.modeler.Gestures class FakeEvent: def __init__(self,sX,sY): self.sX=sX self.sY=sY class DiagramEditorTester: def __init__(self,profile="UML14"): smw=modelerApp.modelerApp() smw.main(loop=0,args=["--profile",profile]) self.smw=smw self.DEM=None for e in smw.project.editorSet.editors(): if isinstance(e,DiagramEditorManager): self.DEM=e assert(self.DEM) def getMainEditor(self): self.smw.processEvents() return self.DEM.subEditors[0] def getCurrentEditor(self): self.smw.processEvents() return self.DEM.getCurrentEditor() def testActionConnection(self,de,actions): de.expossed() for a in actions: if not de.mainWindow.actions.isConnected(a,de): raise("Something missing in activateActions: Action "+str(a)+" is not connected to editor "+str(de)+" after an expose event") de.obscured() for a in actions: if de.mainWindow.actions.isConnected(a,de): raise("Something wrong in obscured: Action "+str(a)+" is still connected to editor "+str(de)+" after an obscyre event") def testCreateInside(self,de,containerA,others): de.expossed() de.selectAll() de.deleteSelection() h=de.mainWindow.actions.getHandler(containerA,de) if not h: raise "Unknown action",containerA h() container=de.currentGesture.onAdd( (300,50) ) for a in others: h=de.mainWindow.actions.getHandler(a,de) if not h: raise "Unknown action",a h() o=de.currentGesture.doIt ( FakeEvent(320,60) ) assert(o) print de.currentGesture p=self.presentationsOfElement(o,de)[0] self.smw.processEvents() assert(container.isPart(o)) de.selectPresentation(p) de.deleteSelection() def testActionCombo(self,de,first,second,link,selfLink=1): de.expossed() h=de.mainWindow.actions.getHandler(first,de) if not h: raise "Unknown action",first h() firstE=de.currentGesture.onAdd((50,50)) firstP=self.presentationsOfElement(firstE,de)[0] thirdE=de.currentGesture.onAdd((200,50)) thirdP=self.presentationsOfElement(thirdE,de)[0] h=de.mainWindow.actions.getHandler(second,de) if not h: raise "Unknown action",second h() secondE=de.currentGesture.onAdd((150,150)) secondP=self.presentationsOfElement(secondE,de)[0] h=de.mainWindow.actions.getHandler(link,de) h() linkE=de.currentGesture.onLink(firstP,secondP,[[50,50],[150,150]]) assert(linkE) linkP=self.presentationsOfElement(linkE,de)[0] assert(linkP.diagram==de.diagram) link2E=de.currentGesture.onLink(thirdP,secondP,[[200,50],[150,150]]) assert(linkE) link2P=self.presentationsOfElement(link2E,de)[0] assert(link2P.diagram==de.diagram) self.testCutCopyPaste(de) self.testActionCombo2(de,firstE,secondE,thirdE,linkE) #self.testCutCopyPaste(de) de.selectAll() de.deleteSelection() if first==second and selfLink and not isinstance(linkE,Generalization) and not isinstance(linkE,Include) and not isinstance(linkE,Extend)\ and not isinstance(linkE,Stimulus): h=de.mainWindow.actions.getHandler(first,de) h() firstE=de.currentGesture.onAdd((50,50)) firstP=self.presentationsOfElement(firstE,de)[0] h=de.mainWindow.actions.getHandler(link,de) h() linkE=de.currentGesture.onLink(firstP,firstP,[[50,50],[55,55]]) assert(linkE) linkP=self.presentationsOfElement(linkE,de)[0] assert(linkP.diagram==de.diagram) self.testActionCombo2(de,firstE,firstE,thirdE,linkE) #self.testCutCopyPaste(de) de.selectAll() de.deleteSelection() def testActionCombo2(self,de,firstE,secondE,thirdE,linkE): self.testMoveCircle(firstE,de) self.testHideAndDrop(linkE,de) self.testDelete(linkE,de) self.testDelete(firstE,de,testHideAfterDelete=0) if firstE!=secondE: self.testDelete(secondE,de,testHideAfterDelete=0) self.testDelete(linkE,de) self.testHideAndDrop(linkE,de) self.testHideAndDrop(firstE,de) self.testRelink(de,linkE,thirdE) self.testRelink(de,linkE,secondE) assert(len(self.presentationsOfElement(linkE,de))==0) self.testDrop(linkE,de) assert(len(self.presentationsOfElement(linkE,de))) def testRelink(self,de,linkE,target): pres,targetP=None,None for p in linkE.presentation: if isinstance(p,AbstractLinkView): pres = p break for p in target.presentation: if isinstance(p,QtPresentationElement) \ and not isinstance(p,TextQtPresentationElement): targetP=p if pres and targetP: if pres.canConnectTo(target,1): pres.connectTo(target,targetP,1) def testAddPlaceAction(self,de,a): h=de.mainWindow.actions.getHandler(a,de) h() if not isinstance(de.currentGesture,smw.modeler.Gestures.AddElementG): raise "action "+str(a)+" does not activate AddElementG" # create an element e=de.currentGesture.doIt(FakeEvent(50,50)) if not isinstance(e,MetaMM.Element): raise str(de.currentGesture.onAdd)+" does not return a model element" if e.presentation.size()==0: raise "Element "+str(e)+" does not have presentations!" name1=e.name e2=de.currentGesture.onAdd((150,150)) name2=e2.name if name1==name2: raise "Each element should have a different name. Action ",a pe=self.presentationsOfElement(e,de) if not pe: raise "Element "+str(e)+" does not a have presentation in the diagram!" self.testMove(e,de) self.testHideAndDrop(e,de) self.testDelete(e,de) def testDelete(self,e,de,testHideAfterDelete=1): for z in range(2): self.smw.processEvents() print "testDelete pass=",z p=self.presentationsOfElement(e,de)[0] de.selection.clear() de.selectPresentation(p) de.project.history.beginModifyCmd() de.deleteSelection() de.project.history.endModifyCmd() print p assert(not p.diagram) de.project.history.undo() assert(p.diagram==de.diagram) de.project.history.redo() assert(not p.diagram) de.project.history.undo() assert(p.diagram==de.diagram) if testHideAfterDelete: print "testHideAndDrop after delete and undo" self.testHideAndDrop(e,de) self.testMove(e,de) def presentationsOfElement(self,e,de): pe=[] for p in e.presentation: if p in de.diagram.content: pe.append(p) return pe def testHideAndDrop(self,e,de): for z in range(2): pres=self.presentationsOfElement(e,de) print "test HideAndDrop pass=",z self.testMove(e,de) de.selection.clear() for p in pres: de.selectPresentation(p) self.testMove(e,de) de.hideSelection() assert(not p.diagram) assert(p not in e.presentation) assert(not len(self.presentationsOfElement(e,de))) de.dropElement(60+100*z,60,e,clone=0,forceDropInDiagram=1) if not len(self.presentationsOfElement(e,de)): raise "Editor "+str(de)+" cannot accept drop "+str(e) def testDrop(self,e,de): de.dropElement(60,60,e,clone=0,forceDropInDiagram=1) assert(len(self.presentationsOfElement(e,de))) def testMove(self,e,de,x=0,y=0): pass def testMoveCircle(self,e,de): y=30 while y<300: x=30 while x<300: self.testMove(e,de,x,y) x=x+30 y=y+30 def testEditor(self,de,placeActions,actionCombos): print "Testing editor ",de assert(isinstance(de,DiagramEditor)) # focusOn is a protected assert("focusOn" not in de.__dict__) self.testActionConnection(de,placeActions) de.expossed() for a in placeActions: self.testAddPlaceAction(de,a) de.selectAll() de.deleteSelection() for c in actionCombos: l=c[0] for first in c[1]: for second in c[2]: print "Testing ",first,"-",l,"-",second self.testActionCombo(de,first,second,l) def testCutCopyPaste(self,de): de.selectAll() de.copy() de.paste() de.cut() de.paste() def testCreateDiagram(self,de,eAction,dMethod): de.expossed() h=de.mainWindow.actions.getHandler(eAction,de) h() if not isinstance(de.currentGesture,smw.modeler.Gestures.AddElementG): raise "action "+str(eAction)+" does not activate AddElementG" # create an element e=de.currentGesture.onAdd((250,150)) newElement=dMethod(e) self.smw.processEvents() assert(newElement) secondEditor=None for p in newElement.presentation: if isinstance(p,Diagram): secondEditor=p.editor assert(secondEditor) secondEditor.deleteDiagram() self.smw.undo() self.smw.redo() --- NEW FILE: PropertyEditorTester.py --- from smw.modeler.DialogEditor import * from smw.smwQtApplication import * from smw.Project import * import types class PEtester(smwQtApplication): def __init__(self,metamodel): smwQtApplication.__init__(self) self.metamodel=metamodel self.project=Project() self.project.root=self.metamodel.Model() self.processEvents() self.move(0,0) self.resize(700,500) def test(self,PEClass,elementsToEdit=[]): assert(issubclass(PEClass,PropertyEditor)) print "Testing ",PEClass.__name__ self.pe=PEClass(self,self.project) self.pe.resize(600,400) self.pe.show() self.processEvents() self.pe.focusOn(None) self.processEvents() supportedElements=[] excludes=self.pe.supercedes() assert(PEClass not in excludes) for c in self.metamodel.__dict__.values(): if type(c)==types.ClassType and \ issubclass(c,self.metamodel.ModelElement): e=c() if self.pe.canEdit(e): supportedElements.append(c) print "Supported elements ",supportedElements if not supportedElements and not elementsToEdit: print "PropertEditor ",PEClass," cannot edit anything!" assert(0) self.project.history.clear() for c in supportedElements: e=c() self.project.history.clear() self.project.history.beginModifyCmd() self.pe.focusOn(e) self.processEvents() self.pe.apply() self.project.history.endModifyCmd() if self.project.history.canUndo(): print "*"*80 print "PropertyEditor ",PEClass,"modifies the model without user interaction." print "*"*80 #assert(0) if issubclass(PEClass,ListPropertyEditor): for c in supportedElements: e=c() self.pe.focusOn(e) self.processEvents() self.pe.add() self.pe.add() self.pe.add() self.pe.delete([0,1,2]) self.pe.apply() self.processEvents() #check if elements really deleted: assert(not eval("e.%s"%self.pe.getAssociationName())) for e in elementsToEdit: assert(self.pe.canEdit(e)) self.pe.focusOn(e) for i in range(10000): self.processEvents() self.pe.apply() self.processEvents() --- NEW FILE: __init__.py --- --- NEW FILE: pycov.py --- import os import sys import getopt __programname__ = "pycov" __version__ = "0.1" __author__ = "Marcus Alanen" import sys import types from profile import Profile import inspect import re import os import string import time import thread import unittest __trace_lock__ = None if __trace_lock__ == None: __trace_lock__ = thread.allocate_lock() __debugCT__ = 0 class FileTestCoverage: def __init__(self, filename, inputfilename = None): self.filename = filename if inputfilename: self.inputfilename = inputfilename else: self.inputfilename = filename self.enabled = 1 self.unused_functions = {} # map of linenumber to usage count self.lines_used = {} lines = self.__getSourceLines__() if lines == -1: self.enabled = 0 return self.max_lines = lines for i in range(lines+1): self.lines_used[i] = 0 self.current_function = None self.current_function_unused = 1 def __fixOldFunc__(self): if self.current_function and self.current_function_unused: self.unused_functions[self.current_function] = 1 #print "Function %s is unused!" % self.current_function self.current_function = None self.current_function_unused = 1 def __getSource__(self): """Returns the source file as an array of lines.""" if not self.enabled: return global __debugCT__ if __debugCT__: print "Getting source for", self.inputfilename try: lines = [None] # dummy line is line number 0 f = file(self.inputfilename) # There must be a faster way, python has already loaded # the file... while 1: t = f.readline() if not t: break lines.append(t) f.close() return lines except: print "*** Could not load", self.inputfilename for i in sys.exc_info(): print i def __getSourceLines__(self): """Counts the lines in the source file.""" try: f = file(self.inputfilename) lines = 0 # There must be a faster way, python has already loaded # the file... while f.readline(): lines += 1 f.close() global __debugCT__ if __debugCT__: print self.inputfilename, "has", lines, "lines." return lines except: print "*** Could not load", self.inputfilename for i in sys.exc_info(): print i return -1 def cover(self, linenumber, bump = 1): """Cover this line of the source file. Basically, just knock its linenumber reference up one step.""" if not self.enabled: return assert(self.lines_used.has_key(linenumber)) self.lines_used[linenumber] += bump def check(self): """Checks the source file line-by-line. This is to find empty lines and comment lines.""" if not self.enabled: return lines = self.__getSource__() # # # # current_class = "" current_class_column = 0 # This keeps empty lines after used regions as used, # but empty lines after unused regions as unused... # => Looks neater? used = 1 # If previous_line_continues previous_line_continues = 0 for i in range(1, self.max_lines+1): theline = lines[i] if self.lines_used[i] > 0: used = 1 ## ## SYNTAX CHECK ## Find classes, functions, exceptions... ## # MATCH CLASS m = re.match("^\s*(class)\s+([\w]+)", theline) if m: current_class = m.group(2) # BUG nested classes? current_class_column = m.start(1) ###print "Found class", current_class continue # MATCH FUNCTION m = re.match("^\s*(def)\s+([\w]+)", theline) if m: self.__fixOldFunc__() output = "" if not current_class or m.start(1) <= current_class_column: current_class = "" output += "Nonclass function " curfunc = m.group(2) # BUG nested functions? if current_class: self.current_function = current_class + "." + curfunc else: self.current_function = curfunc if current_class: output += current_class + "::" output += curfunc if self.lines_used[i] == 0: output += " (unused)" ###################print output continue ## ## Do we continue from the previous line ## if previous_line_continues and self.lines_used[i] == 0: self.lines_used[i] = previous_line_continues ## ## Decide if this line continues on the next line ## if re.search("[\\\[\{\(,]\s*$", theline): previous_line_continues = self.lines_used[i] else: previous_line_continues = 0 # Skip used lines if self.lines_used[i] > 0: self.current_function_unused = 0 continue ## ## EMPTY LINE CHECK ## # Empty lines and lines with comments are "used" if used and re.match("^\s*#", theline): self.lines_used[i] = -1 elif used and re.match("^\s*$", theline): self.lines_used[i] = -1 else: # The ending '}' of hashes if i and self.lines_used[i-1] != 0 and re.match("^\s*}\s*$", theline): self.lines_used[i] = self.lines_used[i-1] else: used = 0 def dump(self, outputstream): """Dumps according to usage, empty lines (N/A) and unused lines.""" if not self.enabled: return #outputstream.write("Test coverage for file %s." % self.filename) for line in range(1, self.max_lines+1): outputstream.write("%s:%d:%d%s" % (self.filename,line, self.lines_used[line], os.linesep)) def dumpHTML(self, outputdir): """Dumps HTML according to usage.""" if not self.enabled: return f = self.filename if f[0] == "/": f = f[1:] try: outpath = outputdir for i in string.split(f, "/")[:-1]: outpath = outpath + os.sep + i try: os.stat(outpath) except: os.mkdir(outpath) output = file(outpath + os.sep + string.split(f, "/")[-1] + ".html", "wb") output.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n") output.write("<html><head>\n") output.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-15\">\n") output.write("<title>") output.write("</title>") output.write("</head>\n") output.write("<body>\n") output.write("<pre>") lines = self.__getSource__() for i in range(1, self.max_lines+1): usecount = self.lines_used[i] # # Output usage count if usecount > 0: output.write("%8d " % usecount) else: output.write(" ") if usecount > 0: output.write("<font color=\"#009900\">") elif usecount == 0: output.write("<font color=\"#ff0000\">") elif usecount < 0: output.write("<font color=\"#999900\">") l = lines[i] l = string.replace(l, "\n", "") l = string.replace(l, "&", "&") l = string.replace(l, "<", "<") l = string.replace(l, ">", ">") output.write(l) output.write("</font>\n") except: for i in sys.exc_info(): print i output.write("</body></html>\n") def summary(self, fd, htmlPrefix): if not self.enabled: return thefuncs = self.unused_functions.keys() if len(thefuncs) == 0: return thefuncs.sort() fd.write("<h3>Unused functions in <a href=\"" + htmlPrefix + self.filename[1:] + ".html\">" + self.filename + "</a>" + "</h3>\n") for i in thefuncs: # The [1:] strips the leading '/' char from the filename # bad for urls... fd.write(i + "<br />\n") class TestCoverage: def __init__(self): self.files = {} def add(self, filename, inputfilename, linenumber, bump = 1): """Cover a linenumber from a file. The appropriate FileTestCoverage object will be added if necessary.""" if not self.files.has_key(filename): self.files[filename] = FileTestCoverage(filename, inputfilename) self.files[filename].cover(linenumber, bump) def end(self): for f in self.files.keys(): self.files[f].check() def dump(self, outputstream): for f in self.files.keys(): self.files[f].dump(outputstream) def dumpHTML(self, outputdir, umask = 022): """Dumps HTML files into current directory.""" oldumask = os.umask(umask) for f in self.files.keys(): self.files[f].dumpHTML(outputdir) os.umask(oldumask) def __mycmp__(self, x, y): if self.files[x].filename < self.files[y].filename: return -1 if self.files[x].filename > self.files[y].filename: return 1 return 0 def summary(self, fd, htmlPrefix): files = self.files.keys() files.sort(self.__mycmp__) for f in files: self.files[f].summary(fd, htmlPrefix) class CoverageProfile: def __init__(self): self.testCoverage = TestCoverage() # Because python mangles the filenames in frame.f_code.co_filename # Argh! self.real_filename_cache = {} # Regular expressions with which we adjust filenames self.regexps = [] def do(self, sourcefile): # BUG # Make the program believe it is really the master Python # program. # DON'T use the __name__: __main__ trick, it doesn't buy you # anything with l = {"trace_function": self.trace } sys.settrace(self.trace) print sourcefile, os.getcwd() try: execfile(sourcefile, l, l) run = None for x in l: try: if x and issubclass(l[x], unittest.TestCase): print "Running tests with unittest..." run = os.getcwd() # BUG BUG BUG # Horrible hack run = re.sub(".*/smw/", "smw/", run) run += "/" + sourcefile run = re.sub(".py$", "", run) run = re.sub("/", ".", run) break except: pass if run: print "Running", run, "instead" unittest.main(run) except: # We catch *everything*, even sys.exit() for i in sys.exc_info(): print "exc", i import traceback traceback.print_exc(file=sys.stderr) sys.settrace(None) def addFromFile(self, fromfilename): f = file(fromfilename) while 1: line = f.readline() if not line: break (filename, linenumber, refcount) = line.split(":") inputfilename = filename # We must remember to mangle the filename when joining for (re_from, re_to) in self.regexps: filename = re.sub(re_from, re_to, filename) self.testCoverage.add(filename, inputfilename, int(linenumber), int(refcount)) def cleanUp(self): # We are done, give the test coverage some breathing room... self.testCoverage.end() def produceHTML(self, outputdir): try: os.mkdir(outputdir) except: pass # It might exist already self.testCoverage.dumpHTML(outputdir) def end(self, fd): if not fd: fd = sys.stdout # Dump statistics self.testCoverage.dump(fd) def createSummary(self, fd, htmlPrefix): if not fd: fd = sys.stdout fd.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n") fd.write("<html><head>\n") fd.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-15\">\n") fd.write("<title>Summary for test coverages</title>") fd.write("</head>\n") fd.write("<body>\n") fd.write("<p><strong>User</strong>: %s</p>\n" % (os.environ.get("USER", "<unknown>"))) # bah, %z doesn't seem to work on this python installation... Use %Z fd.write("<p><strong>Date</strong>: " + time.strftime("%a, %d %b %Y %H:%M:%S %Z", time.localtime()) + "</p>\n") fd.write("<p>Go to the <a href=\".\">files</a>.</p>\n") self.testCoverage.summary(fd, htmlPrefix) fd.write("</body></html>\n") def addRegexps(self, regexplist): self.regexps.extend(regexplist) def trace(self, frame, event, arg): if event == "return": return # This is some magic at the start of the program filename = frame.f_code.co_filename if filename == "<string>": return self.trace global __trace_lock__ __trace_lock__.acquire() try: if self.real_filename_cache.has_key(filename): filename = self.real_filename_cache[filename] else: oldfilename = filename # Some weirdo python again... if filename[0] != "/": filename = os.getcwd() + os.sep + filename else: # Fix filenames like: # /var/tmp/python-2.2.2-root/usr/lib/python2.2/xmlrpclib.py for (re_from, re_to) in self.regexps: filename = re.sub(re_from, re_to, filename) #filename = re.sub("/var/tmp/[^/]*/", "/", filename) # Add to cache self.real_filename_cache[oldfilename] = filename #print filename, frame.f_lineno self.testCoverage.add(filename, filename, frame.f_lineno) except: __trace_lock__.release() raise __trace_lock__.release() return self.trace def usage(): print __programname__ + " -- Python program coverage tester, version " + __version__ print "" print "This program is designed to run a series of unittests, one at a time." print "It gathers information of what Python program lines are executed," print "finally producing a summary of executed lines. Currently, output" print "is available in HTML. A general summary of various data can also" print "be requested." print "" print "Usage: pycov [--help|--version]" print "Usage: pycov [--coverage=file] [--type=(html|txt)] [--outputdir=dir]" print " [--summary=file] program arg1..." print "Usage: pycov --join [--type=(html|txt)] [--outputdir=dir]" print " [--summary=file] coverage..." print "" print "The --join option joins coverage reports." print "The --coverage option tells into which file the resulting coverage" print "should be placed." print "The --summary option produces a (HTML) summary of tests. (N/A)" print "The --outputdir tells into which dir to create the coverage of each file." print "Usually, you want to use this option last with --join, after all tests" print "have been run." print "The --type option specifies output type. (N/A)." print "" longOpts = ["help", "join", "coverage=", "ignore=", "replace=", "type=", "outputdir=", "summary=", "version"] try: opts,applicationArgs = getopt.getopt(sys.argv[1:], "", longOpts) except getopt.GetoptError, e: raise e join = 0 coverage=None type=None outputdir=None summary=None replacethese = [] ignorethese = [] for o,a in opts: if o == "--help": usage() sys.exit(0) if o == "--version": print __programname__ + " " + __version__ sys.exit(0) if o == "--join" and not join: join = 1 continue if o == "--replace": try: splitchar = a[0] (_, re_from, re_to, _) = a.split(splitchar) except: sys.stderr.write("pycov: Error while parsing regular expression '%s'%s" % (a, os.linesep)) sys.exit(1) replacethese.append((re_from, re_to)) continue if o == "--coverage" and not coverage: coverage=a continue if o == "--ignore": ignorethese.append(a) continue if o == "--type": if a != "txt" and a != "html": sys.stderr.write("pycov: option " + a + " to --type not supported." + os.linesep) sys.exit(1) else: sys.stderr.write("pycov: warning: ignoring option to --type, producing HTML" + os.linesep) continue if o == "--outputdir" and not outputdir: outputdir = a continue if o == "--summary" and not summary: summary = a continue # Default fail sys.stderr.write("Unknown option or same option given several times." + os.linesep) sys.exit(1) c = CoverageProfile() c.addRegexps(replacethese) sys.argv = applicationArgs summaryfd = None if summary: # Open now so no chdirs can interfere summaryfd = file(summary, "wb") coveragefd = None if coverage: coveragefd = file(coverage, "wb") # Join previous test coverages if join: for i in applicationArgs: c.addFromFile(i) # Run a test program instead. # # This is perhaps not the best way, # probably depends on how python and PYTHONPATH # is configured. Argh!^2 else: if len(sys.argv) == 0: usage() sys.exit(1) cmd = sys.argv[0] splitted = cmd.split(os.sep) cmd = splitted[-1] path = splitted[:-1] for i in path: if i == "": i = "/" try: os.chdir(i) except: print "Couldn't chdir to", i sys.exit(255) #sys.stderr.write("Executing test %s%s" % (cmd, os.linesep)) c.do(cmd) if coverage: c.end(coveragefd) # Cleanup after writing the coverage c.cleanUp() if outputdir: c.produceHTML(outputdir) if summary: htmlPrefix = "" if outputdir: html_prefix = outputdir c.createSummary(summaryfd, htmlPrefix) --- NEW FILE: unittester.py --- (This appears to be a binary file; contents omitted.) |