Changeset 249
- Timestamp:
- Mon Apr 17 10:48:10 2006
- Files:
-
- trunk/coverage.py (added)
- trunk/tests/doctests/txt/xix-utils-cover-AnnotationParser.txt (added)
- trunk/tests/doctests/txt/xix-utils-cover-annotationToXML.txt (added)
- trunk/tests/doctests/txt/xix-utils-cover-reportToXML.txt (added)
- trunk/tests/doctests/txt/xix-utils-cover-CoverageReportParser.txt (added)
- trunk/scripts/xix-coverage.py (modified) (diff)
- trunk/xix/utils/cover.py (modified) (diff)
- trunk/xix/data (added)
- trunk/xix/data/coverage.xsl (added)
- trunk/xix/data/coverage.css (added)
- trunk/runtests.py (modified) (diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
trunk/scripts/xix-coverage.py
r248 r249 4 4 """ 5 5 6 from xix.utils import cover 7 from optparse import OptionParser 6 from xix.utils.cover import AnnotationParser, annotationToXML, annotationToHTML 7 from xix.utils.cover import CoverageReportParser, reportToXML, _XSLT 8 from optparse import OptionParser 9 10 import lxml.etree as ET 8 11 9 12 import os, sys … … 11 14 from glob import glob 12 15 from commands import getoutput 16 from StringIO import StringIO 13 17 14 18 __author__ = 'Drew Smathers' … … 61 65 fd.close() 62 66 67 def generateXML(reportdir, source): 68 print 'Generated coverage annotations' 69 parser = AnnotationParser() 70 for root, dirs, files in os.walk(pj(source)): 71 covers = [ f for f in files if f[-6:] == ',cover' ] 72 for cover in covers: 73 srcname = pj(root, cover.split(',cover')[0]) 74 srcname = srcname.replace(os.path.sep, '.')[:-3] 75 print 'generating XML/HTML for : ', srcname 76 xml_fname = 'coverage_' + srcname.replace('.', '-') + '.xml' 77 html_fname = 'coverage_' + srcname.replace('.', '-') + '.html' 78 annt = parser.parse(open(pj(root, cover))) 79 xml = annotationToXML(annt, tree=True) 80 fd = open(pj(reportdir, xml_fname), 'w') 81 xml.write(fd) 82 xslt = ET.parse(StringIO(_XSLT)) 83 transform = ET.XSLT(xslt) 84 html = transform(xml, modname="'%s'" % srcname) 85 fd.close() 86 fd = open(pj(reportdir, html_fname), 'w') 87 html.write(fd) 88 fd.close() 89 90 _REPORT_XSLT = '''<?xml version="1.0"?> 91 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 92 <xsl:output method="html"/> 93 <xsl:param name="packagename"/> 94 <xsl:template match="/"> 95 <html><head><title>Coverage Report for <xsl:value-of select="$packagename"/></title> 96 <link rel="stylesheet" type="text/css" href="coverage.css"/></head> 97 <body> 98 <h2>Coverage Report for <xsl:value-of select="$packagename"/></h2> 99 <table><tr><th>Module Name</th><th>Statements</th><th>Executed</th><th>Coverage</th></tr> 100 <xsl:for-each select="//module"> 101 <tr> 102 <td> 103 <a> 104 <xsl:attribute name="href"> 105 <xsl:text>coverage_</xsl:text><xsl:value-of select="translate(@name, '.', '-')"/><xsl:text>.html</xsl:text> 106 </xsl:attribute> 107 <xsl:value-of select="@name"/> 108 </a> 109 </td> 110 <td><xsl:value-of select="@statements"/></td> 111 <td><xsl:value-of select="@executed"/></td> 112 <td><xsl:value-of select="@coverage"/></td> 113 </tr> 114 </xsl:for-each> 115 </table> 116 </body></html> 117 </xsl:template> 118 119 </xsl:stylesheet>''' 120 121 def generateIndex(reportdir, source): 122 report = CoverageReportParser().parse(open('.report')) 123 xml = reportToXML(report, tree=True) 124 xslt = ET.parse(StringIO(_REPORT_XSLT)) 125 transform = ET.XSLT(xslt) 126 html = transform(xml, packagename="'%s'" % source) 127 fd = open(pj(reportdir, 'index.html'), 'w') 128 html.write(fd) 129 fd.close() 130 63 131 def main(opts): 64 132 if not os.path.exists('coverage.py'): … … 66 134 sys.exit(-1) 67 135 prepare_fs(opts.source, opts.copy_compiled, opts.exclude_dirs, opts.depends) 136 _mkdir(opts.report_dir) 137 reportdir = os.path.abspath(opts.report_dir) 68 138 os.chdir('.xcoverage') 69 139 print getoutput('python coverage.py -x %s' % opts.command) 70 140 annotate(opts.source) 71 os.chdir('..') 72 _mkdir(opts.report_dir) 73 xdir = os.path.abspath('.xcoverage') 141 linkmap = generateXML(reportdir, opts.source) 142 generateIndex(reportdir, opts.source) 143 print 'Report complete. See ' + pj(reportdir, 'index.html') 74 144 75 145 -
trunk/xix/utils/cover.py
r247 r249 3 3 4 4 from UserList import UserList 5 import sys 5 import sys, os 5 5 from StringIO import StringIO 6 6 import lxml.etree as ET … … 23 23 24 24 class AnnotationParser: 25 """example usage: 26 27 Say we have a file as follows: 28 29 >>> from xix.utils.mock import File 30 >>> t = '''> def foo(a): 31 ... > if a: 32 ... ! print 'hello' 33 ... # just a comment 34 ... 35 ... > r = lambda : 45 36 ... 37 ... ''' 38 >>> f = File(t) 39 40 Create a parser instance and call parse with file object: 41 42 >>> parser = AnnotationParser() 43 >>> ant = parser.parse(f) 44 45 The annotation object should be created sucessfully. Let's see: 46 47 >>> covered = [ line for line in ant if line.covered ] 48 >>> isexec = [ line for line in ant if line.isexec ] 49 >>> notexec = [ line for line in ant if not line.isexec ] 50 >>> for line in covered: 51 ... print line.text 52 def foo(a): 53 if a: 54 r = lambda : 45 55 >>> for line in isexec: 56 ... print line.text 57 def foo(a): 58 if a: 59 print \'hello\' 60 r = lambda : 45 61 >>> for line in notexec: 62 ... print line.text 63 # just a comment 64 <BLANKLINE> 65 <BLANKLINE> 66 <BLANKLINE> 67 25 """Parser for annotation files generated by coverage. 68 26 """ 69 27 def parse(self, input): … … 84 42 85 43 def annotationToXML(annotation, tree=False): 86 """example: 44 """Transform annotation object to XML string or ElementTree instance 45 if tree is True. 87 46 88 >>> s = '''> def foo(a): 89 ... ! print "hello" 90 ... # a comment''' 91 >>> from xix.utils.mock import File 92 >>> ant = AnnotationParser().parse(File(s)) 93 >>> result = annotationToXML(ant) 94 95 Parse the result using lxml: 96 97 >>> buffer = StringIO('<?xml version="1.0"?>' + result) 98 >>> doc = ET.parse(buffer) 99 >>> root = doc.getroot() 100 >>> print root.tag 101 coverageAnnotation 102 >>> for node in root.getchildren(): 103 ... print node.tag, node.attrib['executable'], node.attrib['covered'] 104 ... print 'Text:', node.text 105 ... 106 line true true 107 Text: def foo(a): 108 line true false 109 Text: print "hello" 110 line false false 111 Text: # a comment 47 @param annotation: Annotation instance 48 @param tree: set to true to return ElementTree instance. 112 49 """ 113 50 etree = _annotationToXML(annotation) … … 128 65 129 66 130 def annotationToHTML(annotation, xslt=None, tree=False): 67 def annotationToHTML(annotation, xml=None, xslt=None, tree=False): 68 """Transform annotation object to HTML string or ElementTree instance 69 if tree is True. 70 71 @param annotation: Annotation instance 72 @param xslt: xslt source for transformation 73 @param tree: set to true to return ElementTree instance. 74 """ 131 75 style = xslt or _XSLT 132 76 if not hasattr(style, 'read'): … … 140 84 html.write(buffer) 141 85 return buffer.getvalue() 86 87 ########################################### 88 # Coverage reports 89 ########################################### 90 91 class CoverageReport(UserList): 92 package_name = None 93 94 class CoverageReportEntry: 95 96 def __init__(self, modname, statements, executed, coverage, missing): 97 self.modname = modname 98 self.statements = statements 99 self.executed = executed 100 self.coverage = coverage 101 self.missing = missing 102 103 class CoverageReportParser: 104 105 def parse(self, input): 106 fd = input 107 if not hasattr(input, 'read'): 108 fd = open(input) 109 report = CoverageReport() 110 for line in fd.readlines()[2:-2]: 111 tokens = line.split() 112 modname, stmts, execd, coverage = tokens[:4] 113 modname = modname.replace(os.path.sep, '.') 114 missed = [ tk.replace(',','') for tk in tokens[4:] ] 115 report.append(CoverageReportEntry(modname, stmts, execd, coverage, missed)) 116 return report 117 118 119 def reportToXML(report, tree=False): 120 """Transform report object to XML representation as string or ElementTree 121 instance if tree arg is set to True. 122 123 @param report: report instance 124 @param tree: set to true to return ElementTree instance 125 """ 126 etree = _reportToXML(report) 127 if tree: 128 return etree 129 buffer = StringIO() 130 etree.write(buffer) 131 return buffer.getvalue() 132 133 def _reportToXML(report): 134 root = ET.Element('coverage-report') 135 for entry in report: 136 elm = ET.SubElement(root, 'module') 137 attr = elm.attrib 138 attr['name'] = entry.modname 139 attr['statements'] = entry.statements 140 attr['executed'] = entry.executed 141 attr['coverage'] = entry.coverage 142 melm = ET.SubElement(elm, 'missing-ranges') 143 for missed in entry.missing: 144 start_end = missed.split('-') 145 if len(start_end) == 2: 146 start, end = start_end 147 else: 148 start = end = start_end[0] 149 relm = ET.SubElement(melm, 'range') 150 relm.attrib['start'] = start 151 relm.attrib['end'] = end 152 return ET.ElementTree(root) 142 153 143 154 … … 145 156 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 146 157 <xsl:output method="html"/> 147 <xsl:param name="mod uleName"/>158 <xsl:param name="modname"/> 147 158 <xsl:template match="/"> 148 <html><head><title>Coverage Results for <xsl:value-of select="$moduleName"/></title> 159 <xsl:message>modname is <xsl:value-of select="$modname"/></xsl:message> 160 <html><head><title>Coverage Results for <xsl:value-of select="$modname"/></title> 149 161 <link rel="stylesheet" type="text/css" href="coverage.css"/></head> 150 162 <body> 151 <h2>Coverage Results for <xsl:value-of select="$mod uleName"/></h2>163 <h2>Coverage Results for <xsl:value-of select="$modname"/></h2> 151 163 <div class="annotated-source-code"> 152 164 <xsl:for-each select="/coverageAnnotation/line"> -
trunk/runtests.py
r248 r249 10 10 try: 11 11 from zope.testing import doctest 12 print 'using zope doctest'13 12 except ImportError: 14 13 import doctest
