VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/testmanager/webui/wuireport.py@ 61292

Last change on this file since 61292 was 61292, checked in by vboxsync, 9 years ago

arg. more bugs.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.3 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: wuireport.py 61292 2016-05-30 13:03:50Z vboxsync $
3
4"""
5Test Manager WUI - Reports.
6"""
7
8__copyright__ = \
9"""
10Copyright (C) 2012-2015 Oracle Corporation
11
12This file is part of VirtualBox Open Source Edition (OSE), as
13available from http://www.virtualbox.org. This file is free software;
14you can redistribute it and/or modify it under the terms of the GNU
15General Public License (GPL) as published by the Free Software
16Foundation, in version 2 as it comes in the "COPYING" file of the
17VirtualBox OSE distribution. VirtualBox OSE is distributed in the
18hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
19
20The contents of this file may alternatively be used under the terms
21of the Common Development and Distribution License Version 1.0
22(CDDL) only, as it comes in the "COPYING.CDDL" file of the
23VirtualBox OSE distribution, in which case the provisions of the
24CDDL are applicable instead of those of the GPL.
25
26You may elect to license modified versions of this file under the
27terms and conditions of either the GPL or the CDDL or both.
28"""
29__version__ = "$Revision: 61292 $"
30
31
32# Validation Kit imports.
33from common import webutils;
34from testmanager.webui.wuicontentbase import WuiContentBase, WuiTmLink, WuiSvnLinkWithTooltip;
35from testmanager.webui.wuihlpgraph import WuiHlpGraphDataTable, WuiHlpBarGraph;
36from testmanager.webui.wuitestresult import WuiTestSetLink;
37from testmanager.webui.wuiadmintestcase import WuiTestCaseDetailsLink;
38from testmanager.webui.wuiadmintestbox import WuiTestBoxDetailsLink;
39from testmanager.core.report import ReportModelBase;
40
41
42class WuiReportSummaryLink(WuiTmLink):
43 """ Generic report summary link. """
44
45 def __init__(self, sSubject, aIdSubjects, sName = WuiContentBase.ksShortReportLink,
46 tsNow = None, cPeriods = None, cHoursPerPeriod = None, fBracketed = False, dExtraParams = None):
47 from testmanager.webui.wuimain import WuiMain;
48 dParams = {
49 WuiMain.ksParamAction: WuiMain.ksActionReportSummary,
50 WuiMain.ksParamReportSubject: sSubject,
51 WuiMain.ksParamReportSubjectIds: aIdSubjects,
52 };
53 if dExtraParams is not None:
54 dParams.update(dExtraParams);
55 if tsNow is not None:
56 dParams[WuiMain.ksParamEffectiveDate] = tsNow;
57 if cPeriods is not None:
58 dParams[WuiMain.ksParamReportPeriods] = cPeriods;
59 if cPeriods is not None:
60 dParams[WuiMain.ksParamReportPeriodInHours] = cHoursPerPeriod;
61 WuiTmLink.__init__(self, sName, WuiMain.ksScriptName, dParams, fBracketed = fBracketed);
62
63
64class WuiReportBase(WuiContentBase):
65 """
66 Base class for the reports.
67 """
68
69 def __init__(self, oModel, dParams, fSubReport = False, fnDPrint = None, oDisp = None):
70 WuiContentBase.__init__(self, fnDPrint = fnDPrint, oDisp = oDisp);
71 self._oModel = oModel;
72 self._dParams = dParams;
73 self._fSubReport = fSubReport;
74 self._sTitle = None;
75
76 # Additional URL parameters for reports
77 self._dExtraParams = {};
78 dCurParams = None if oDisp is None else oDisp.getParameters();
79 if dCurParams is not None:
80 from testmanager.webui.wuimain import WuiMain;
81 for sExtraParam in [ WuiMain.ksParamReportPeriods, WuiMain.ksParamReportPeriodInHours,
82 WuiMain.ksParamEffectiveDate, ]:
83 if sExtraParam in dCurParams:
84 self._dExtraParams[sExtraParam] = dCurParams[sExtraParam];
85
86
87 def generateNavigator(self, sWhere):
88 """
89 Generates the navigator (manipulate _dParams).
90 Returns HTML.
91 """
92 assert sWhere == 'top' or sWhere == 'bottom';
93
94 return '';
95
96 def generateReportBody(self):
97 """
98 This is overridden by the child class to generate the report.
99 Returns HTML.
100 """
101 return '<h3>Must override generateReportBody!</h3>';
102
103 def show(self):
104 """
105 Generate the report.
106 Returns (sTitle, HTML).
107 """
108
109 sTitle = self._sTitle if self._sTitle is not None else type(self).__name__;
110 sReport = self.generateReportBody();
111 if not self._fSubReport:
112 sReport = self.generateNavigator('top') + sReport + self.generateNavigator('bottom');
113 sTitle = self._oModel.sSubject + ' - ' + sTitle; ## @todo add subject to title in a proper way!
114
115 sReport += '\n\n<!-- HEYYOU: sSubject=%s aidSubjects=%s -->\n\n' % (self._oModel.sSubject, self._oModel.aidSubjects);
116 return (sTitle, sReport);
117
118
119class WuiReportSuccessRate(WuiReportBase):
120 """
121 Generates a report displaying the success rate over time.
122 """
123
124 def generateReportBody(self):
125 self._sTitle = 'Success rate';
126
127 adPeriods = self._oModel.getSuccessRates();
128
129 sReport = '';
130
131 oTable = WuiHlpGraphDataTable('Period', [ 'Succeeded', 'Skipped', 'Failed' ]);
132
133 #for i in range(len(adPeriods) - 1, -1, -1):
134 for i, dStatuses in enumerate(adPeriods):
135 cSuccess = dStatuses[ReportModelBase.ksTestStatus_Success] + dStatuses[ReportModelBase.ksTestStatus_Skipped];
136 cTotal = cSuccess + dStatuses[ReportModelBase.ksTestStatus_Failure];
137 sPeriod = self._oModel.getPeriodDesc(i);
138 if cTotal > 0:
139 iPctSuccess = dStatuses[ReportModelBase.ksTestStatus_Success] * 100 / cTotal;
140 iPctSkipped = dStatuses[ReportModelBase.ksTestStatus_Skipped] * 100 / cTotal;
141 iPctFailure = dStatuses[ReportModelBase.ksTestStatus_Failure] * 100 / cTotal;
142 oTable.addRow(sPeriod, [ iPctSuccess, iPctSkipped, iPctFailure ],
143 [ '%s%% (%d)' % (iPctSuccess, dStatuses[ReportModelBase.ksTestStatus_Success]),
144 '%s%% (%d)' % (iPctSkipped, dStatuses[ReportModelBase.ksTestStatus_Skipped]),
145 '%s%% (%d)' % (iPctFailure, dStatuses[ReportModelBase.ksTestStatus_Failure]), ]);
146 else:
147 oTable.addRow(sPeriod, [ 0, 0, 0 ], [ '0%', '0%', '0%' ]);
148
149 cTotalNow = adPeriods[0][ReportModelBase.ksTestStatus_Success];
150 cTotalNow += adPeriods[0][ReportModelBase.ksTestStatus_Skipped];
151 cSuccessNow = cTotalNow;
152 cTotalNow += adPeriods[0][ReportModelBase.ksTestStatus_Failure];
153 sReport += '<p>Current success rate: ';
154 if cTotalNow > 0:
155 sReport += '%s%% (thereof %s%% skipped)</p>\n' \
156 % ( cSuccessNow * 100 / cTotalNow, adPeriods[0][ReportModelBase.ksTestStatus_Skipped] * 100 / cTotalNow);
157 else:
158 sReport += 'N/A</p>\n'
159
160 oGraph = WuiHlpBarGraph('success-rate', oTable, self._oDisp);
161 oGraph.setRangeMax(100);
162 sReport += oGraph.renderGraph();
163
164 return sReport;
165
166
167class WuiReportFailuresBase(WuiReportBase):
168 """
169 Common parent of WuiReportFailureReasons and WuiReportTestCaseFailures.
170 """
171
172 def _splitSeriesIntoMultipleGraphs(self, aidSorted, cMaxSeriesPerGraph = 8):
173 """
174 Splits the ID array into one or more arrays, making sure we don't
175 have too many series per graph.
176 Returns array of ID arrays.
177 """
178 if len(aidSorted) <= cMaxSeriesPerGraph + 2:
179 return [aidSorted,];
180 cGraphs = len(aidSorted) / cMaxSeriesPerGraph + (len(aidSorted) % cMaxSeriesPerGraph != 0);
181 cPerGraph = len(aidSorted) / cGraphs + (len(aidSorted) % cGraphs != 0);
182
183 aaoRet = [];
184 cLeft = len(aidSorted);
185 iSrc = 0;
186 while cLeft > 0:
187 cThis = cPerGraph;
188 if cLeft <= cPerGraph + 2:
189 cThis = cLeft;
190 elif cLeft <= cPerGraph * 2 + 4:
191 cThis = cLeft / 2;
192 aaoRet.append(aidSorted[iSrc : iSrc + cThis]);
193 iSrc += cThis;
194 cLeft -= cThis;
195 return aaoRet;
196
197 def _formatEdgeOccurenceSubject(self, oTransient):
198 """
199 Worker for _formatEdgeOccurence that child classes overrides to format
200 their type of subject data in the best possible way.
201 """
202 _ = oTransient;
203 assert False;
204 return '';
205
206 def _formatEdgeOccurence(self, oTransient):
207 """
208 Helper for formatting the transients.
209 oTransient is of type ReportFailureReasonTransient or ReportTestCaseFailureTransient.
210 """
211 sHtml = u'<li>';
212 if oTransient.fEnter: sHtml += 'Since ';
213 else: sHtml += 'Until ';
214 sHtml += WuiSvnLinkWithTooltip(oTransient.iRevision, oTransient.sRepository, fBracketed = 'False').toHtml();
215 sHtml += u', %s: ' % (WuiTestSetLink(oTransient.idTestSet, self.formatTsShort(oTransient.tsDone),
216 fBracketed = False).toHtml(), )
217 sHtml += self._formatEdgeOccurenceSubject(oTransient);
218 sHtml += u'</li>\n';
219 return sHtml;
220
221 def _generateTransitionList(self, oSet):
222 """
223 Generates the enter and leave lists.
224 """
225 # Skip this if we're looking at builds.
226 if self._oModel.sSubject in [self._oModel.ksSubBuild,] and len(self._oModel.aidSubjects) in [1, 2]:
227 return u'';
228
229 sHtml = u'<h4>Movements:</h4>\n' \
230 u'<ul>\n';
231 if len(oSet.aoEnterInfo) == 0 and len(oSet.aoLeaveInfo) == 0:
232 sHtml += u'<li>No changes</li>\n';
233 else:
234 for oTransient in oSet.aoEnterInfo:
235 sHtml += self._formatEdgeOccurence(oTransient);
236 for oTransient in oSet.aoLeaveInfo:
237 sHtml += self._formatEdgeOccurence(oTransient);
238 sHtml += u'</ul>\n';
239
240 return sHtml;
241
242
243 def _formatSeriesNameForTable(self, oSet, idKey):
244 """ Formats the series name for the HTML table. """
245 _ = oSet;
246 return '<td>%d</td>' % (idKey,);
247
248 def _formatRowValueForTable(self, oRow, oPeriod, cColsPerSeries):
249 """ Formats a row value for the HTML table. """
250 _ = oPeriod;
251 if oRow is None:
252 return u'<td colspan="%d"> </td>' % (cColsPerSeries,);
253 if cColsPerSeries == 2:
254 return u'<td align="right">%u%%</td><td align="center">%u / %u</td>' \
255 % (oRow.cHits * 100 / oRow.cTotal, oRow.cHits, oRow.cTotal);
256 return u'<td align="center">%u</td>' % (oRow.cHits,);
257
258 def _formatSeriesTotalForTable(self, oSet, idKey, cColsPerSeries):
259 """ Formats the totals cell for a data series in the HTML table. """
260 dcTotalPerId = getattr(oSet, 'dcTotalPerId', None);
261 if cColsPerSeries == 2:
262 return u'<td align="right">%u%%</td><td align="center">%u/%u</td>' \
263 % (oSet.dcHitsPerId[idKey] * 100 / dcTotalPerId[idKey], oSet.dcHitsPerId[idKey], dcTotalPerId[idKey]);
264 return u'<td align="center">%u</td>' % (oSet.dcHitsPerId[idKey],);
265
266 def _generateTableForSet(self, oSet, sColumnName, aidSorted = None, iSortColumn = 0,
267 fWithTotals = True, cColsPerSeries = None):
268 """
269 Turns the set into a table.
270
271 Returns raw html.
272 """
273 sHtml = u'<table class="tmtbl-report-set" width="100%%">\n';
274 if cColsPerSeries is None:
275 cColsPerSeries = 2 if hasattr(oSet, 'dcTotalPerId') else 1;
276
277 # Header row.
278 sHtml += u' <tr><thead><th></th><th>%s</th>' % (webutils.escapeElem(sColumnName),)
279 for iPeriod, oPeriod in enumerate(reversed(oSet.aoPeriods)):
280 sHtml += u'<th colspan="%d">%s%s</th>' % ( cColsPerSeries, webutils.escapeElem(oPeriod.sDesc),
281 '&#x25bc;' if iPeriod == iSortColumn else '');
282 if fWithTotals:
283 sHtml += u'<th colspan="%d">Total%s</th>' % (cColsPerSeries,
284 '&#x25bc;' if iSortColumn == len(oSet.aoPeriods) else '');
285 sHtml += u'</thead></td>\n';
286
287 # Each data series.
288 if aidSorted is None:
289 aidSorted = oSet.dSubjects.keys();
290 sHtml += u' <tbody>\n';
291 for iRow, idKey in enumerate(aidSorted):
292 sHtml += u' <tr class="%s">' % ('tmodd' if iRow & 1 else 'tmeven',);
293 sHtml += u'<td align="left">#%u</td>' % (iRow + 1,);
294 sHtml += self._formatSeriesNameForTable(oSet, idKey);
295 for oPeriod in reversed(oSet.aoPeriods):
296 oRow = oPeriod.dRowsById.get(idKey, None);
297 sHtml += self._formatRowValueForTable(oRow, oPeriod, cColsPerSeries);
298 if fWithTotals:
299 sHtml += self._formatSeriesTotalForTable(oSet, idKey, cColsPerSeries);
300 sHtml += u' </tr>\n';
301 sHtml += u' </tbody>\n';
302 sHtml += u'</table>\n';
303 return sHtml;
304
305
306class WuiReportFailuresWithTotalBase(WuiReportFailuresBase):
307 """
308 For ReportPeriodSetWithTotalBase.
309 """
310
311 def _formatSeriedNameForGraph(self, oSubject):
312 """
313 Format the subject name for the graph.
314 """
315 return str(oSubject);
316
317 def _getSortedIds(self, oSet, fByTotal = None):
318 """
319 Get default sorted subject IDs and which column.
320 """
321
322 if fByTotal is None:
323 fByTotal = oSet.cMaxTotal < 10;
324
325 if fByTotal is True:
326 # Sort the total.
327 aidSortedRaw = sorted(oSet.dSubjects,
328 key = lambda idKey: oSet.dcHitsPerId[idKey] * 10000 / oSet.dcTotalPerId[idKey],
329 reverse = True);
330 iColumn = len(oSet.aoPeriods);
331 else:
332 # Sort by NOW column.
333 dTmp = {};
334 for idKey in oSet.dSubjects:
335 oRow = oSet.aoPeriods[-1].dRowsById.get(idKey, None);
336 if oRow is None: dTmp[idKey] = 0;
337 else: dTmp[idKey] = oRow.cHits * 10000 / max(1, oRow.cTotal);
338 aidSortedRaw = sorted(dTmp, key = lambda idKey: dTmp[idKey], reverse = True);
339 iColumn = 0;
340 return (aidSortedRaw, iColumn);
341
342 def _generateGraph(self, oSet, sIdBase, aidSortedRaw):
343 """
344 Generates graph.
345 """
346 sHtml = u'';
347 fGenerateGraph = len(aidSortedRaw) <= 6 and len(aidSortedRaw) > 0; ## Make this configurable.
348 if fGenerateGraph:
349 # Figure the graph width for all of them.
350 uPctMax = max(oSet.uMaxPct, oSet.cMaxHits * 100 / oSet.cMaxTotal);
351 uPctMax = max(uPctMax + 2, 10);
352
353 for _, aidSorted in enumerate(self._splitSeriesIntoMultipleGraphs(aidSortedRaw, 8)):
354 asNames = [];
355 for idKey in aidSorted:
356 oSubject = oSet.dSubjects[idKey];
357 asNames.append(self._formatSeriedNameForGraph(oSubject));
358
359 oTable = WuiHlpGraphDataTable('Period', asNames);
360
361 for _, oPeriod in enumerate(reversed(oSet.aoPeriods)):
362 aiValues = [];
363 asValues = [];
364
365 for idKey in aidSorted:
366 oRow = oPeriod.dRowsById.get(idKey, None);
367 if oRow is not None:
368 uPct = oRow.cHits * 100 / oRow.cTotal;
369 aiValues.append(uPct);
370 asValues.append('%u%% (%u/%u)' % (uPct, oRow.cHits, oRow.cTotal));
371 else:
372 aiValues.append(0);
373 asValues.append('0');
374
375 oTable.addRow(oPeriod.sDesc, aiValues, asValues);
376
377 if True: # pylint: disable=W0125
378 aiValues = [];
379 asValues = [];
380 for idKey in aidSorted:
381 uPct = oSet.dcHitsPerId[idKey] * 100 / oSet.dcTotalPerId[idKey];
382 aiValues.append(uPct);
383 asValues.append('%u%% (%u/%u)' % (uPct, oSet.dcHitsPerId[idKey], oSet.dcTotalPerId[idKey]));
384 oTable.addRow('Totals', aiValues, asValues);
385
386 oGraph = WuiHlpBarGraph(sIdBase, oTable, self._oDisp);
387 oGraph.setRangeMax(uPctMax);
388 sHtml += '<br>\n';
389 sHtml += oGraph.renderGraph();
390 return sHtml;
391
392
393
394class WuiReportFailureReasons(WuiReportFailuresBase):
395 """
396 Generates a report displaying the failure reasons over time.
397 """
398
399 def _formatEdgeOccurenceSubject(self, oTransient):
400 return u'%s / %s' % ( webutils.escapeElem(oTransient.oReason.oCategory.sShort),
401 webutils.escapeElem(oTransient.oReason.sShort),);
402
403 def _formatSeriesNameForTable(self, oSet, idKey):
404 oReason = oSet.dSubjects[idKey];
405 sHtml = u'<td>';
406 sHtml += u'%s / %s' % ( webutils.escapeElem(oReason.oCategory.sShort), webutils.escapeElem(oReason.sShort),);
407 sHtml += u'</td>';
408 return sHtml;
409
410
411 def generateReportBody(self):
412 self._sTitle = 'Failure reasons';
413
414 #
415 # Get the data and sort the data series in descending order of badness.
416 #
417 oSet = self._oModel.getFailureReasons();
418 aidSortedRaw = sorted(oSet.dSubjects, key = lambda idReason: oSet.dcHitsPerId[idReason], reverse = True);
419
420 #
421 # Generate table and transition list. These are the most useful ones with the current graph machinery.
422 #
423 sHtml = self._generateTableForSet(oSet, 'Test Cases', aidSortedRaw, len(oSet.aoPeriods));
424 sHtml += self._generateTransitionList(oSet);
425
426 #
427 # Check if most of the stuff is without any assign reason, if so, skip
428 # that part of the graph so it doesn't offset the interesting bits.
429 #
430 fIncludeWithoutReason = True;
431 for oPeriod in reversed(oSet.aoPeriods):
432 if oPeriod.cWithoutReason > oSet.cMaxHits * 4:
433 fIncludeWithoutReason = False;
434 sHtml += '<p>Warning: Many failures without assigned reason!</p>\n';
435 break;
436
437 #
438 # Generate the graph.
439 #
440 fGenerateGraph = len(aidSortedRaw) <= 9 and len(aidSortedRaw) > 0; ## Make this configurable.
441 if fGenerateGraph:
442 aidSorted = aidSortedRaw;
443
444 asNames = [];
445 for idReason in aidSorted:
446 oReason = oSet.dSubjects[idReason];
447 asNames.append('%s / %s' % (oReason.oCategory.sShort, oReason.sShort,) )
448 if fIncludeWithoutReason:
449 asNames.append('No reason');
450
451 oTable = WuiHlpGraphDataTable('Period', asNames);
452
453 cMax = oSet.cMaxHits;
454 for _, oPeriod in enumerate(reversed(oSet.aoPeriods)):
455 aiValues = [];
456
457 for idReason in aidSorted:
458 oRow = oPeriod.dRowsById.get(idReason, None);
459 iValue = oRow.cHits if oRow is not None else 0;
460 aiValues.append(iValue);
461
462 if fIncludeWithoutReason:
463 aiValues.append(oPeriod.cWithoutReason);
464 if oPeriod.cWithoutReason > cMax:
465 cMax = oPeriod.cWithoutReason;
466
467 oTable.addRow(oPeriod.sDesc, aiValues);
468
469 oGraph = WuiHlpBarGraph('failure-reason', oTable, self._oDisp);
470 oGraph.setRangeMax(max(cMax + 1, 3));
471 sHtml += oGraph.renderGraph();
472 return sHtml;
473
474
475class WuiReportTestCaseFailures(WuiReportFailuresWithTotalBase):
476 """
477 Generates a report displaying the failure reasons over time.
478 """
479
480 def _formatEdgeOccurenceSubject(self, oTransient):
481 sHtml = u'%s ' % ( webutils.escapeElem(oTransient.oSubject.sName),);
482 sHtml += WuiTestCaseDetailsLink(oTransient.oSubject.idTestCase, fBracketed = False).toHtml();
483 return sHtml;
484
485 def _formatSeriesNameForTable(self, oSet, idKey):
486 oTestCase = oSet.dSubjects[idKey];
487 sHtml = u'<td>';
488 sHtml += WuiReportSummaryLink(ReportModelBase.ksSubTestCase, oTestCase.idTestCase, sName = oTestCase.sName,
489 dExtraParams = self._dExtraParams).toHtml();
490 sHtml += u' ';
491 sHtml += WuiTestCaseDetailsLink(oTestCase.idTestCase).toHtml();
492 sHtml += u'</td>';
493 return sHtml;
494
495 def _formatSeriedNameForGraph(self, oSubject):
496 return oSubject.sName;
497
498 def generateReportBody(self):
499 self._sTitle = 'Test Case Failures';
500 oSet = self._oModel.getTestCaseFailures();
501 (aidSortedRaw, iSortColumn) = self._getSortedIds(oSet);
502
503 sHtml = self._generateTableForSet(oSet, 'Test Cases', aidSortedRaw, iSortColumn);
504 sHtml += self._generateTransitionList(oSet);
505 sHtml += self._generateGraph(oSet, 'testcase-graph', aidSortedRaw);
506 return sHtml;
507
508
509class WuiReportTestCaseArgsFailures(WuiReportFailuresWithTotalBase):
510 """
511 Generates a report displaying the failure reasons over time.
512 """
513
514 @staticmethod
515 def _formatName(oTestCaseArgs):
516 if oTestCaseArgs.sSubName is not None and len(oTestCaseArgs.sSubName) > 0:
517 sName = u'%s / %s' % ( oTestCaseArgs.oTestCase.sName, oTestCaseArgs.sSubName, );
518 else:
519 sName = u'%s / #%u' % ( oTestCaseArgs.oTestCase.sName, oTestCaseArgs.idTestCaseArgs, );
520 return sName;
521
522 def _formatEdgeOccurenceSubject(self, oTransient):
523 sHtml = u'%s ' % ( webutils.escapeElem(self._formatName(oTransient.oSubject)),);
524 sHtml += WuiTestCaseDetailsLink(oTransient.oSubject.idTestCase, fBracketed = False).toHtml();
525 return sHtml;
526
527 def _formatSeriesNameForTable(self, oSet, idKey):
528 oTestCaseArgs = oSet.dSubjects[idKey];
529 sHtml = u'<td>';
530 sHtml += WuiReportSummaryLink(ReportModelBase.ksSubTestCaseArgs, oTestCaseArgs.idTestCaseArgs,
531 sName = self._formatName(oTestCaseArgs), dExtraParams = self._dExtraParams).toHtml();
532 sHtml += u' ';
533 sHtml += WuiTestCaseDetailsLink(oTestCaseArgs.idTestCase).toHtml();
534 sHtml += u'</td>';
535 return sHtml;
536
537 def _formatSeriedNameForGraph(self, oSubject):
538 return self._formatName(oSubject);
539
540 def generateReportBody(self):
541 self._sTitle = 'Test Case Variation Failures';
542 oSet = self._oModel.getTestCaseVariationFailures();
543 (aidSortedRaw, iSortColumn) = self._getSortedIds(oSet);
544
545 sHtml = self._generateTableForSet(oSet, 'Test Case Variations', aidSortedRaw, iSortColumn);
546 sHtml += self._generateTransitionList(oSet);
547 sHtml += self._generateGraph(oSet, 'testcasearg-graph', aidSortedRaw);
548 return sHtml;
549
550
551
552class WuiReportTestBoxFailures(WuiReportFailuresWithTotalBase):
553 """
554 Generates a report displaying the failure reasons over time.
555 """
556
557 def _formatEdgeOccurenceSubject(self, oTransient):
558 sHtml = u'%s ' % ( webutils.escapeElem(oTransient.oSubject.sName),);
559 sHtml += WuiTestBoxDetailsLink(oTransient.oSubject.idTestBox, fBracketed = False).toHtml();
560 return sHtml;
561
562 def _formatSeriesNameForTable(self, oSet, idKey):
563 oTestBox = oSet.dSubjects[idKey];
564 sHtml = u'<td>';
565 sHtml += WuiReportSummaryLink(ReportModelBase.ksSubTestBox, oTestBox.idTestBox, sName = oTestBox.sName,
566 dExtraParams = self._dExtraParams).toHtml();
567 sHtml += u' ';
568 sHtml += WuiTestBoxDetailsLink(oTestBox.idTestBox).toHtml();
569 sHtml += u'</td>';
570 return sHtml;
571
572 def _formatSeriedNameForGraph(self, oSubject):
573 return oSubject.sName;
574
575 def generateReportBody(self):
576 self._sTitle = 'Test Box Failures';
577 oSet = self._oModel.getTestBoxFailures();
578 (aidSortedRaw, iSortColumn) = self._getSortedIds(oSet);
579
580 sHtml = self._generateTableForSet(oSet, 'Test Boxes', aidSortedRaw, iSortColumn);
581 sHtml += self._generateTransitionList(oSet);
582 sHtml += self._generateGraph(oSet, 'testbox-graph', aidSortedRaw);
583 return sHtml;
584
585
586class WuiReportSummary(WuiReportBase):
587 """
588 Summary report.
589 """
590
591 def generateReportBody(self):
592 self._sTitle = 'Summary';
593 sHtml = '<p>This will display several reports and listings useful to get an overview of %s (id=%s).</p>' \
594 % (self._oModel.sSubject, self._oModel.aidSubjects,);
595
596 aoReports = [];
597
598 aoReports.append(WuiReportSuccessRate( self._oModel, self._dParams, fSubReport = True,
599 fnDPrint = self._fnDPrint, oDisp = self._oDisp));
600 aoReports.append(WuiReportTestCaseFailures(self._oModel, self._dParams, fSubReport = True,
601 fnDPrint = self._fnDPrint, oDisp = self._oDisp));
602 if self._oModel.sSubject == ReportModelBase.ksSubTestCase:
603 aoReports.append(WuiReportTestCaseArgsFailures(self._oModel, self._dParams, fSubReport = True,
604 fnDPrint = self._fnDPrint, oDisp = self._oDisp));
605 aoReports.append(WuiReportTestBoxFailures( self._oModel, self._dParams, fSubReport = True,
606 fnDPrint = self._fnDPrint, oDisp = self._oDisp));
607 aoReports.append(WuiReportFailureReasons( self._oModel, self._dParams, fSubReport = True,
608 fnDPrint = self._fnDPrint, oDisp = self._oDisp));
609
610 for oReport in aoReports:
611 (sTitle, sContent) = oReport.show();
612 sHtml += '<br>'; # drop this layout hack
613 sHtml += '<div>';
614 sHtml += '<h3>%s</h3>\n' % (webutils.escapeElem(sTitle),);
615 sHtml += sContent;
616 sHtml += '</div>';
617
618 return sHtml;
619
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette