Commits

Ned Batchelder committed 0186e68

HTML report now has an index.html.

  • Participants
  • Parent commits 8621280

Comments (0)

Files changed (5)

 
 HTML reporting, and continued refactoring.
 
-- HTML reports and annotation of source files: use the new -b switch.
+- HTML reports and annotation of source files: use the new -b switch.  THanks
+  to George Song for code, inspiration and guidance.
 
 - Annotation into a directory (-a -d) behaves differently.  The annotated files
   are named with their hierarchy flattened so that same-named files from

File coverage/html.py

         self.directory = None
         self.source_tmpl = Templite(data("htmlfiles/pyfile.html"), globals())
         
+        self.files = []
+
     def report(self, morfs, directory=None, omit_prefixes=None):
         assert directory, "must provide a directory for html reporting"
         
         # Process all the files.
         self.report_files(self.html_file, morfs, directory, omit_prefixes)
 
+        # Write the index file.
+        self.index_file()
+
     def html_file(self, cu, statements, excluded, missing):
         """Generate an HTML file for one source file."""
         
         n_mis = len(missing)
         n_run = n_stm - n_mis
         if n_stm > 0:
-            pc_cov = 100.0 * float(n_run) / n_stm
+            pc_cov = 100.0 * n_run / n_stm
         else:
             pc_cov = 100.0
 
             }
             lines.append(lineinfo)
 
-        html_filename = os.path.join(self.directory, cu.flat_rootname())
-        html_filename += ".html"
-        fhtml = open(html_filename, 'w')
+        # Write the HTML page for this file.
+        html_filename = cu.flat_rootname() + ".html"
+        html_path = os.path.join(self.directory, html_filename)
+        fhtml = open(html_path, 'w')
         fhtml.write(self.source_tmpl.render(locals()))
         fhtml.close()
 
+        # Save this file's information for the index file.
+        self.files.append({
+            'stm': n_stm,
+            'run': n_run,
+            'exc': n_exc,
+            'mis': n_mis,
+            'pc_cov': pc_cov,
+            'html_filename': html_filename,
+            'cu': cu,
+            })
+
+    def index_file(self):
+        """Write the index.html file for this report."""
+        index_tmpl = Templite(data("htmlfiles/index.html"), globals())
+
+        files = self.files
+        
+        total_stm = sum([f['stm'] for f in files])
+        total_run = sum([f['run'] for f in files])
+        total_exc = sum([f['exc'] for f in files])
+        if total_stm:
+            total_cov = 100.0 * total_run / total_stm
+        else:
+            total_cov = 100.0
+
+        fhtml = open(os.path.join(self.directory, "index.html"), "w")
+        fhtml.write(index_tmpl.render(locals()))
+        fhtml.close()
+
 
 # Helpers for templates
 

File coverage/htmlfiles/index.html

+<!doctype html PUBLIC "-//W3C//DTD html 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<title>Coverage report</title>
+<link rel='stylesheet' href='style.css' type='text/css'>
+</head>
+<body>
+
+<div id='header'>
+    <div class='content'>
+        <h1>Coverage report: 
+            <span class='pc_cov'>{{total_cov|format_pct}}%</span>
+        </h1>
+    </div>
+</div>
+
+<div id='index'>
+<table class='index'>
+<tr>
+    <th class='name'>Module</th>
+    <th>statements</th>
+    <th>run</th>
+    <th>excluded</th>
+    <th>coverage</th>
+</tr>
+{% for file in files %}
+<tr>
+    <td class='name'><a href='{{file.html_filename}}'>{{file.cu.name}}</a></td>
+    <td>{{file.stm}}</td>
+    <td>{{file.run}}</td>
+    <td>{{file.exc}}</td>
+    <td>{{file.pc_cov|format_pct}}%</td>
+</tr>
+{% endfor %}
+<tr class='total'>
+<td class='name'>Total</td>
+<td>{{total_stm}}</td>
+<td>{{total_run}}</td>
+<td>{{total_exc}}</td>
+<td>{{total_cov|format_pct}}%</td>
+</tr>
+</table>
+</div>
+
+<div id='footer'>
+    <div class='content'>
+        <p>
+            <a class='nav' href='http://bitbucket.org/ned/coveragepy/'>coverage.py v{{__version__}}</a>
+        </p>
+    </div>
+</div>
+
+</body>
+</html>

File coverage/htmlfiles/pyfile.html

 </table>
 </div>
 
-<div id='footer'>
-    <div class='content'>
-        <p>
-            <a class='nav' href='http://bitbucket.org/ned/coveragepy/'>coverage.py v{{__version__}}</a>
-        </p>
-    </div>
-</div>
-
 </body>
 </html>

File coverage/htmlfiles/style.css

 /* CSS styles for coverage.py */
 /* Page-wide styles */
-html, body, h1, h2, h3, p, td {
+html, body, h1, h2, h3, p, td, th {
     margin: 0;
 	padding: 0;
 	border: 0;
 
 /* Set baseline grid to 16 pt. */
 body {
+    font-family: georgia, serif;
     font-size: 1em;
     }
 
     line-height: 1.3333em;   /* 16/12 */
     }
 
+table {
+    border-collapse: collapse;
+    }
+
 a.nav {
     text-decoration: none;
     color: inherit;
 #header {
     background: #f8f8f8;
     width: 100%;
-    font-family: georgia, serif;
     border-bottom: 1px solid #eee;
     }
 
     font-style: italic;
     }
 
+#index {
+    margin: 1em 0 0 3em;
+    }
+
 /* Header styles */
 .content {
-    padding: 1em 3em .5em 3em;
+    padding: 1em 3em;
     }
 
 h1 {
 .text p.hide {
     background: inherit;
     }
+
+/* index styles */
+#index td, #index th {
+    text-align: right;
+    width: 6em;
+    padding: .25em 0;
+    border-bottom: 1px solid #eee;
+    }
+#index th {
+    font-style: italic;
+    color: #333;
+    border-bottom: 1px solid #ccc;
+    }
+#index td.name, #index th.name {
+    text-align: left;
+    width: auto;
+    height: 1.5em;
+    }
+#index td.name a {
+    text-decoration: none;
+    color: #000;
+    }
+#index td.name a:hover {
+    text-decoration: underline;
+    color: #000;
+    }
+#index tr.total {
+    font-weight: bold;
+    }
+#index tr.total td {
+    padding: .25em 0;
+    border-top: 1px solid #ccc;
+    border-bottom: none;
+    }