[GRASS-SVN] r61440 - grass/trunk/lib/python/gunittest

svn_grass at osgeo.org svn_grass at osgeo.org
Mon Jul 28 20:37:26 PDT 2014


Author: wenzeslaus
Date: 2014-07-28 20:37:26 -0700 (Mon, 28 Jul 2014)
New Revision: 61440

Added:
   grass/trunk/lib/python/gunittest/multireport.py
Log:
gunittest: script to collect data from several reports (uses keyvalue files as input, has HTML output only)

Added: grass/trunk/lib/python/gunittest/multireport.py
===================================================================
--- grass/trunk/lib/python/gunittest/multireport.py	                        (rev 0)
+++ grass/trunk/lib/python/gunittest/multireport.py	2014-07-29 03:37:26 UTC (rev 61440)
@@ -0,0 +1,281 @@
+# -*- coding: utf-8 -*-
+
+import sys
+import os
+import argparse
+import itertools
+import datetime
+import operator
+from collections import defaultdict
+
+import matplotlib
+matplotlib.use('Agg')
+import matplotlib.pyplot as plt
+from matplotlib.dates import date2num
+
+from grass.gunittest.checkers import text_to_keyvalue
+from grass.gunittest.utils import ensure_dir
+from grass.gunittest.reporters import success_to_html_percent
+
+
+class TestResultSummary(object):
+    def __init__(self):
+        self.timestamp = None
+        self.svn_revision = None
+
+        self.total = None
+        self.successes = None
+        self.failures = None
+        self.errors = None
+
+        self.skipped = []
+        self.expected_failures = []
+        self.unexpected_successes = []
+
+        self.files_total = None
+        self.files_successes = None
+        self.files_failures = None
+
+        self.tested_modules = []
+        self.tested_dirs = []
+        self.test_files_authors = []
+        self.time = []
+        self.names = []
+
+        self.report = None
+
+
+def tests_plot(x, xlabels, results, filename):
+
+    total = [result.total for result in results]
+    successes = [result.successes for result in results]
+    # TODO: document: counting errors and failures together
+    failures = [result.failures + result.errors for result in results]
+
+    fig = plt.figure()
+
+    graph = fig.add_subplot(111)
+
+    # Plot the data as a red line with round markers
+    graph.plot(x, total, 'b-o')
+    graph.plot(x, successes, 'g-o')
+    graph.plot(x, failures, 'r-o')
+    fig.autofmt_xdate()
+
+    # Set the xtick locations to correspond to just the dates you entered.
+    graph.set_xticks(x)
+
+    # Set the xtick labels to correspond to just the dates you entered.
+    graph.set_xticklabels(xlabels)
+
+    fig.savefig(filename)
+
+
+def files_plot(x, xlabels, results, filename):
+    total = [result.files_total for result in results]
+    successes = [result.files_successes for result in results]
+    failures = [result.files_failures for result in results]
+
+    fig = plt.figure()
+
+    graph = fig.add_subplot(111)
+
+    # Plot the data as a red line with round markers
+    graph.plot(x, total, 'b-o')
+    graph.plot(x, successes, 'g-o')
+    graph.plot(x, failures, 'r-o')
+    #fig.autofmt_xdate(bottom=0.2, rotation=30, ha='left')
+    fig.autofmt_xdate()
+
+    # Set the xtick locations to correspond to just the dates you entered.
+    graph.set_xticks(x)
+
+    # Set the xtick labels to correspond to just the dates you entered.
+    graph.set_xticklabels(xlabels)
+
+    fig.savefig(filename)
+
+
+def info_plot(x, xlabels, results, filename):
+
+    modules = [len(result.tested_modules) for result in results]
+    names = [len(result.names) for result in results]
+    authors = [len(result.test_files_authors) for result in results]
+
+    fig = plt.figure()
+
+    graph = fig.add_subplot(111)
+
+    # Plot the data as a red line with round markers
+    graph.plot(x, names, 'b-o', label="Test files")
+    graph.plot(x, modules, 'g-o', label="Tested modules")
+    graph.plot(x, authors, 'r-o', label="Test authors")
+    fig.autofmt_xdate()
+
+    # Now add the legend with some customizations.
+    graph.legend(loc='upper center', shadow=True)
+
+    # Set the xtick locations to correspond to just the dates you entered.
+    graph.set_xticks(x)
+
+    # Set the xtick labels to correspond to just the dates you entered.
+    graph.set_xticklabels(xlabels)
+
+    fig.savefig(filename)
+
+
+# TODO: solve the directory inconsitencies, implemement None
+def main_page(results, filename, images, captions, title='Test reports',
+              directory=None):
+    filename = os.path.join(directory, filename)
+    with open(filename, 'w') as page:
+        page.write(
+            '<html><body>'
+            '<h1>{title}</h1>'
+            '<table>'
+            '<thead><tr>'
+            '<th>Date (timestamp)</th><th>SVN revision</th><th>Name</th>'
+            '<th>Successful files</th><th>Successful tests</th>'
+            '</tr></thead>'
+            '<tbody>'
+            .format(title=title)
+            )
+        for result in results:
+            # TODO: include name to summary file
+            name = os.path.basename(result.report)
+            per_test = success_to_html_percent(
+                total=result.total, successes=result.successes)
+            per_file = success_to_html_percent(
+                total=result.files_total, successes=result.files_successes)
+            report_path = os.path.relpath(path=result.report, start=directory)
+            page.write(
+                '<tr>'
+                '<td><a href={report_path}/index.html>{result.timestamp}</a></td>'
+                '<td>{result.svn_revision}</td>'
+                '<td><a href={result.report}/index.html>{name}</a></td>'
+                '<td>{pfiles}</td><td>{ptests}</td>'
+                '</tr>'
+                .format(result=result, name=name, report_path=report_path,
+                        pfiles=per_file, ptests=per_test))
+        page.write('</tbody></table>')
+        for image, caption in itertools.izip(images, captions):
+            page.write(
+                '<h3>{caption}<h3>'
+                '<img src="{image}" alt="{caption}" title="{caption}">'
+                .format(image=image, caption=caption))
+        page.write('</body></html>')
+
+
+def main():
+
+    parser = argparse.ArgumentParser(
+        description='Create overall report from several individual test reports')
+    parser.add_argument('reports', metavar='report_directory',
+                        type=str, nargs='+',
+                        help='Directories with reports')
+    parser.add_argument('--output', dest='output', action='store',
+                        default='testreports_summary',
+                        help='Output directory')
+    parser.add_argument('--timestamps', dest='timestamps', action='store_true',
+                        help='Use file timestamp instead of date in test summary')
+
+    args = parser.parse_args()
+    output = args.output
+    reports = args.reports
+    use_timestamps = args.timestamps
+
+    ensure_dir(output)
+
+    all_results = []
+    results_in_locations = defaultdict(list)
+
+    for report in reports:
+        try:
+            summary_file = os.path.join(report, 'test_keyvalue_result.txt')
+            summary = text_to_keyvalue(open(summary_file).read(), sep='=')
+            if use_timestamps:
+                test_timestamp = datetime.datetime.fromtimestamp(os.path.getmtime(summary_file))
+            else:
+                test_timestamp = datetime.datetime.strptime(summary['timestamp'], "%Y-%m-%d %H:%M:%S")
+
+            result = TestResultSummary()
+            result.timestamp = test_timestamp
+            result.total = summary['total']
+            result.successes = summary['successes']
+            result.failures = summary['failures']
+            result.errors = summary['errors']
+
+            result.files_total = summary['files_total']
+            result.files_successes = summary['files_successes']
+            result.files_failures = summary['files_failures']
+
+            result.svn_revision = str(summary['svn_revision'])
+            result.tested_modules = summary['tested_modules']
+            result.names = summary['names']
+            result.test_files_authors = summary['test_files_authors']
+            result.report = report
+
+            # let's consider no location as valid state and use 'unknown'
+            location = summary.get('location', 'unknown')
+            results_in_locations[location].append(result)
+
+            all_results.append(result)
+            del result
+        except KeyError as e:
+            print 'File %s does not have right values (%s)' % (report, e.message) 
+
+    locations_main_page = open(os.path.join(output, 'index.html'), 'w')
+    locations_main_page.write(
+        '<html><body>'
+        '<h1>Test reports accoring to locations</h1>'
+        '<table>'
+        '<thead><tr>'
+        '<th>Location</th>'
+        '<th>Successful files</th><th>Successful tests</th>'
+        '</tr></thead>'
+        '<tbody>'
+        )
+
+    for location, results in results_in_locations.iteritems():
+        results = sorted(results, key=operator.attrgetter('timestamp'))
+        # TODO: document: location shortcut must be a valid dir name
+        directory = os.path.join(output, location)
+        ensure_dir(directory)
+
+        x = [date2num(result.timestamp) for result in results]
+        xlabels = [result.timestamp.strftime("%Y-%m-%d") + ' (r' + result.svn_revision + ')' for result in results]
+        tests_plot(x=x, xlabels=xlabels, results=results,
+                   filename=os.path.join(directory, 'tests_plot.png'))
+        files_plot(x=x, xlabels=xlabels, results=results,
+                   filename=os.path.join(directory, 'files_plot.png'))
+        info_plot(x=x, xlabels=xlabels, results=results,
+                  filename=os.path.join(directory, 'info_plot.png'))
+
+        main_page(results=results, filename='index.html',
+                  images=['tests_plot.png', 'files_plot.png', 'info_plot.png'],
+                  captions=['Success of individual tests', 'Success of test files',
+                            'Additional information'],
+                  directory=directory)
+
+        files_successes = sum(result.files_successes for result in results)
+        files_total = sum(result.files_total for result in results)
+        successes = sum(result.successes for result in results)
+        total = sum(result.total for result in results)
+        per_test = success_to_html_percent(
+            total=total, successes=successes)
+        per_file = success_to_html_percent(
+            total=files_total, successes=files_successes)
+        locations_main_page.write(
+            '<tr>'
+            '<td><a href={location}/index.html>{location}</a></td>'
+            '<td>{pfiles}</td><td>{ptests}</td>'
+            '</tr>'
+            .format(location=location,
+                    pfiles=per_file, ptests=per_test))
+    locations_main_page.write('</tbody></table>')
+    locations_main_page.write('</body></html>')
+    locations_main_page.close()
+    return 0
+
+if __name__ == '__main__':
+    sys.exit(main())


Property changes on: grass/trunk/lib/python/gunittest/multireport.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native



More information about the grass-commit mailing list