report.py revision f81680c018729fd4499e1e200d04b48c4b90127c
1# /usr/bin/python2.6
2#
3# Copyright 2011 Google Inc. All Rights Reserved.
4# Author: kbaclawski@google.com (Krystian Baclawski)
5#
6
7import logging
8import os.path
9
10
11RESULT_DESCRIPTION = {
12    'ERROR': 'DejaGNU errors',
13    'FAIL': 'Failed tests',
14    'NOTE': 'DejaGNU notices',
15    'PASS': 'Passed tests',
16    'UNRESOLVED': 'Unresolved tests',
17    'UNSUPPORTED': 'Unsupported tests',
18    'UNTESTED': 'Not executed tests',
19    'WARNING': 'DejaGNU warnings',
20    'XFAIL': 'Expected test failures',
21    'XPASS': 'Unexpectedly passed tests'}
22
23RESULT_GROUPS = {
24    'Successes': ['PASS', 'XFAIL'],
25    'Failures': ['FAIL', 'XPASS', 'UNRESOLVED'],
26    'Suppressed': ['!FAIL', '!XPASS', '!UNRESOLVED', '!ERROR'],
27    'Framework': ['UNTESTED', 'UNSUPPORTED', 'ERROR', 'WARNING', 'NOTE']}
28
29ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
30
31
32def _GetResultDescription(name):
33  if name.startswith('!'):
34    name = name[1:]
35
36  try:
37    return RESULT_DESCRIPTION[name]
38  except KeyError:
39    raise ValueError('Unknown result: "%s"' % name)
40
41
42def _PrepareSummary(res_types, summary):
43  def GetResultCount(res_type):
44    return summary.get(res_type, 0)
45
46  return [(_GetResultDescription(rt), GetResultCount(rt))
47          for rt in res_types]
48
49
50def _PrepareTestList(res_types, tests):
51  def GetTestsByResult(res_type):
52    return [(test.name, test.variant or '')
53            for test in sorted(tests)
54            if test.result == res_type]
55
56  return [(_GetResultDescription(rt), GetTestsByResult(rt))
57          for rt in res_types if rt != 'PASS']
58
59
60def Generate(test_runs, manifests):
61  """Generate HTML report from provided test runs.
62
63  Args:
64    test_runs: DejaGnuTestRun objects list.
65    manifests: Manifest object list that will drive test result suppression.
66
67  Returns:
68    String to which the HTML report was rendered.
69  """
70  tmpl_args = []
71
72  for test_run_id, test_run in enumerate(test_runs):
73    logging.info('Generating report for: %s.', test_run)
74
75    test_run.CleanUpTestResults()
76    test_run.SuppressTestResults(manifests)
77
78    # Generate summary and test list for each result group
79    groups = {}
80
81    for res_group, res_types in RESULT_GROUPS.items():
82      summary_all = _PrepareSummary(res_types, test_run.summary)
83      tests_all = _PrepareTestList(res_types, test_run.results)
84
85      has_2nd = lambda tuple2: bool(tuple2[1])
86      summary = filter(has_2nd, summary_all)
87      tests = filter(has_2nd, tests_all)
88
89      if summary or tests:
90        groups[res_group] = {'summary': summary, 'tests': tests}
91
92    tmpl_args.append({
93        'id': test_run_id,
94        'name': '%s @%s' % (test_run.tool, test_run.board),
95        'groups': groups})
96
97  logging.info('Rendering report in HTML format.')
98
99  try:
100    from django import template
101    from django.template import loader
102    from django.conf import settings
103  except ImportError:
104    logging.error('Django framework not installed!')
105    logging.error('Failed to generate report in HTML format!')
106    return ''
107
108  settings.configure(DEBUG=True, TEMPLATE_DEBUG=True,
109                     TEMPLATE_DIRS=(ROOT_PATH,))
110
111  tmpl = loader.get_template('report.html')
112  ctx = template.Context({'test_runs': tmpl_args})
113
114  return tmpl.render(ctx)
115