Changeset 61286 in vbox for trunk/src/VBox/ValidationKit/testmanager/webui
- Timestamp:
- May 30, 2016 12:22:41 PM (9 years ago)
- svn:sync-xref-src-repo-rev:
- 107578
- Location:
- trunk/src/VBox/ValidationKit/testmanager/webui
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ValidationKit/testmanager/webui/wuiadmintestbox.py
r61220 r61286 35 35 # Validation Kit imports. 36 36 from common import utils; 37 from testmanager.webui.wuicontentbase import Wui ListContentWithActionBase, WuiFormContentBase, WuiLinkBase, WuiSvnLink, \38 Wui TmLink, WuiSpanText, WuiRawHtml;37 from testmanager.webui.wuicontentbase import WuiContentBase, WuiListContentWithActionBase, WuiFormContentBase, WuiLinkBase, \ 38 WuiSvnLink, WuiTmLink, WuiSpanText, WuiRawHtml; 39 39 from testmanager.core.db import TMDatabaseConnection; 40 40 from testmanager.core.schedgroup import SchedGroupLogic, SchedGroupData; … … 42 42 from testmanager.core.testset import TestSetData; 43 43 from testmanager.core.db import isDbTimestampInfinity; 44 45 46 47 class WuiTestBoxDetailsLink(WuiTmLink): 48 """ Test box details link by ID. """ 49 50 def __init__(self, idTestBox, sName = WuiContentBase.ksShortDetailsLink, fBracketed = False, tsNow = None): 51 from testmanager.webui.wuiadmin import WuiAdmin; 52 dParams = { 53 WuiAdmin.ksParamAction: WuiAdmin.ksActionTestBoxDetails, 54 TestBoxData.ksParam_idTestBox: idTestBox, 55 }; 56 if tsNow is not None: 57 dParams[WuiAdmin.ksParamEffectiveDate] = tsNow; ## ?? 58 WuiTmLink.__init__(self, sName, WuiAdmin.ksScriptName, dParams, fBracketed = fBracketed); 59 self.idTestBox = idTestBox; 60 44 61 45 62 -
trunk/src/VBox/ValidationKit/testmanager/webui/wuimain.py
r61278 r61286 81 81 ksActionReportRate = 'ReportRate'; 82 82 ksActionReportTestCaseFailures = 'ReportTestCaseFailures'; 83 ksActionReportTestBoxFailures = 'ReportTestBoxFailures'; 83 84 ksActionReportFailureReasons = 'ReportFailureReasons'; 84 85 ksActionGraphWiz = 'GraphWiz'; … … 272 273 dCurParams = oSrvGlue.getParameters() 273 274 if dCurParams is not None: 274 asActionUrlExtras = [ self.ksParamItemsPerPage, self.ksParamEffectiveDate, self.ksParamEffectivePeriod, ]; 275 for sExtraParam in asActionUrlExtras: 275 for sExtraParam in [ self.ksParamItemsPerPage, self.ksParamEffectiveDate, self.ksParamEffectivePeriod, ]: 276 276 if sExtraParam in dCurParams: 277 sExtraTimeNav += '&%s' % webutils.encodeUrlParams({sExtraParam: dCurParams[sExtraParam]}) 277 sExtraTimeNav += '&%s' % (webutils.encodeUrlParams({sExtraParam: dCurParams[sExtraParam]}),) 278 279 # Additional URL parameters for reports 280 sExtraReports = ''; 281 if dCurParams is not None: 282 for sExtraParam in [ self.ksParamReportPeriods, self.ksParamReportPeriodInHours, self.ksParamEffectiveDate, ]: 283 if sExtraParam in dCurParams: 284 sExtraReports += '&%s' % (webutils.encodeUrlParams({sExtraParam: dCurParams[sExtraParam]}),) 278 285 279 286 # Shorthand to keep within margins. … … 298 305 'Reports', sActUrlBase + self.ksActionReportSummary, 299 306 [ 300 [ 'Summary', sActUrlBase + self.ksActionReportSummary ], 301 [ 'Success Rate', sActUrlBase + self.ksActionReportRate ], 302 [ 'Test Case Failures', sActUrlBase + self.ksActionReportTestCaseFailures ], 303 [ 'Failure Reasons', sActUrlBase + self.ksActionReportFailureReasons ], 307 [ 'Summary', sActUrlBase + self.ksActionReportSummary + sExtraReports ], 308 [ 'Success Rate', sActUrlBase + self.ksActionReportRate + sExtraReports ], 309 [ 'Test Case Failures', sActUrlBase + self.ksActionReportTestCaseFailures + sExtraReports ], 310 [ 'TestBox Failures', sActUrlBase + self.ksActionReportTestBoxFailures + sExtraReports ], 311 [ 'Failure Reasons', sActUrlBase + self.ksActionReportFailureReasons + sExtraReports ], 304 312 ] 305 313 ], -
trunk/src/VBox/ValidationKit/testmanager/webui/wuireport.py
r61275 r61286 36 36 from testmanager.webui.wuitestresult import WuiTestSetLink; 37 37 from testmanager.webui.wuiadmintestcase import WuiTestCaseDetailsLink; 38 from testmanager.webui.wuiadmintestbox import WuiTestBoxDetailsLink; 38 39 from testmanager.core.report import ReportModelBase; 39 40 … … 43 44 44 45 def __init__(self, sSubject, aIdSubjects, sName = WuiContentBase.ksShortReportLink, 45 tsNow = None, cPeriods = None, cHoursPerPeriod = None, fBracketed = False ):46 tsNow = None, cPeriods = None, cHoursPerPeriod = None, fBracketed = False, dExtraParams = None): 46 47 from testmanager.webui.wuimain import WuiMain; 47 48 dParams = { … … 50 51 WuiMain.ksParamReportSubjectIds: aIdSubjects, 51 52 }; 53 if dExtraParams is not None: 54 dParams.update(dExtraParams); 52 55 if tsNow is not None: 53 56 dParams[WuiMain.ksParamEffectiveDate] = tsNow; … … 70 73 self._fSubReport = fSubReport; 71 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 72 86 73 87 def generateNavigator(self, sWhere): … … 287 301 288 302 289 290 291 class WuiReportFailureReasons(WuiReportFailuresBase): 292 """ 293 Generates a report displaying the failure reasons over time. 294 """ 295 296 def _formatEdgeOccurenceSubject(self, oTransient): 297 return u'%s / %s' % ( webutils.escapeElem(oTransient.oReason.oCategory.sShort), 298 webutils.escapeElem(oTransient.oReason.sShort),); 299 300 def _formatSeriesNameForTable(self, oSet, idKey): 301 oReason = oSet.dSubjects[idKey]; 302 sHtml = '<td>' 303 sHtml += u'%s / %s' % ( webutils.escapeElem(oReason.oCategory.sShort), webutils.escapeElem(oReason.sShort),); 304 sHtml += '</td>' 305 return sHtml; 306 307 308 def generateReportBody(self): 309 self._sTitle = 'Failure reasons'; 310 311 # 312 # Get the data and sort the data series in descending order of badness. 313 # 314 oSet = self._oModel.getFailureReasons(); 315 aidSortedRaw = sorted(oSet.dSubjects, key = lambda idReason: oSet.dcHitsPerId[idReason], reverse = True); 316 317 # 318 # Generate table and transition list. These are the most useful ones with the current graph machinery. 319 # 320 sHtml = self._generateTableForSet(oSet, 'Test Cases', aidSortedRaw); 321 sHtml += self._generateTransitionList(oSet); 322 323 # 324 # Check if most of the stuff is without any assign reason, if so, skip 325 # that part of the graph so it doesn't offset the interesting bits. 326 # 327 fIncludeWithoutReason = True; 328 for oPeriod in reversed(oSet.aoPeriods): 329 if oPeriod.cWithoutReason > oSet.cMaxHits * 4: 330 fIncludeWithoutReason = False; 331 sHtml += '<p>Warning: Many failures without assigned reason!</p>\n'; 332 break; 333 334 # 335 # Generate the graph. 336 # 337 fGenerateGraph = len(aidSortedRaw) <= 9 and len(aidSortedRaw) > 0; ## Make this configurable. 338 if fGenerateGraph: 339 aidSorted = aidSortedRaw; 340 341 asNames = []; 342 for idReason in aidSorted: 343 oReason = oSet.dSubjects[idReason]; 344 asNames.append('%s / %s' % (oReason.oCategory.sShort, oReason.sShort,) ) 345 if fIncludeWithoutReason: 346 asNames.append('No reason'); 347 348 oTable = WuiHlpGraphDataTable('Period', asNames); 349 350 cMax = oSet.cMaxHits; 351 for _, oPeriod in enumerate(reversed(oSet.aoPeriods)): 352 aiValues = []; 353 354 for idReason in aidSorted: 355 oRow = oPeriod.dRowsById.get(idReason, None); 356 iValue = oRow.cHits if oRow is not None else 0; 357 aiValues.append(iValue); 358 359 if fIncludeWithoutReason: 360 aiValues.append(oPeriod.cWithoutReason); 361 if oPeriod.cWithoutReason > cMax: 362 cMax = oPeriod.cWithoutReason; 363 364 oTable.addRow(oPeriod.sDesc, aiValues); 365 366 oGraph = WuiHlpBarGraph('failure-reason', oTable, self._oDisp); 367 oGraph.setRangeMax(max(cMax + 1, 3)); 368 sHtml += oGraph.renderGraph(); 369 return sHtml; 370 371 372 class WuiReportTestCaseFailures(WuiReportFailuresBase): 373 """ 374 Generates a report displaying the failure reasons over time. 375 """ 376 377 def _formatEdgeOccurenceSubject(self, oTransient): 378 sHtml = u'%s ' % ( webutils.escapeElem(oTransient.oTestCase.sName),); 379 sHtml += WuiTestCaseDetailsLink(oTransient.oTestCase.idTestCase, fBracketed = False).toHtml(); 380 return sHtml; 381 382 def _formatSeriesNameForTable(self, oSet, idKey): 383 oTestCase = oSet.dSubjects[idKey]; 384 sHtml = '<td>' 385 sHtml += WuiReportSummaryLink(ReportModelBase.ksSubTestCase, oTestCase.idTestCase, sName = oTestCase.sName).toHtml(); 386 sHtml += u' '; 387 sHtml += WuiTestCaseDetailsLink(oTestCase.idTestCase).toHtml(); 388 sHtml += '</td>' 389 return sHtml; 390 391 def generateReportBody(self): 392 self._sTitle = 'Test Case Failures'; 393 394 395 # 396 # Get the data and sort the data series in descending order of badness. 397 # 398 oSet = self._oModel.getTestCaseFailures(); 303 class WuiReportFailuresWithTotalBase(WuiReportFailuresBase): 304 """ 305 For ReportPeriodSetWithTotalBase. 306 """ 307 308 def _getSortedIds(self, oSet): 309 """ 310 Get default sorted subject IDs. 311 """ 312 399 313 if self._oModel.tsNow is not None and False: 400 314 # Sort the total. … … 410 324 else: dTmp[idKey] = oRow.cHits * 10000 / max(1, oRow.cTotal); 411 325 aidSortedRaw = sorted(dTmp, key = lambda idKey: dTmp[idKey], reverse = True); 412 413 # 414 # Generate table and transition list. These are the most useful ones with the current graph machinery. 415 # 416 sHtml = self._generateTableForSet(oSet, 'Test Cases', aidSortedRaw); 417 sHtml += self._generateTransitionList(oSet); 418 419 # 420 # Generate the graph. 421 # 326 return aidSortedRaw; 327 328 def _generateGraph(self, oSet, sIdBase, aidSortedRaw): 329 """ 330 Generates graph. 331 """ 332 sHtml = u''; 422 333 fGenerateGraph = len(aidSortedRaw) <= 6 and len(aidSortedRaw) > 0; ## Make this configurable. 423 334 if fGenerateGraph: … … 459 370 oTable.addRow('Totals', aiValues, asValues); 460 371 461 oGraph = WuiHlpBarGraph( 'testcase-failures', oTable, self._oDisp);372 oGraph = WuiHlpBarGraph(sIdBase, oTable, self._oDisp); 462 373 oGraph.setRangeMax(uPctMax); 463 374 sHtml += '<br>\n'; 464 375 sHtml += oGraph.renderGraph(); 465 376 return sHtml; 377 378 379 380 class WuiReportFailureReasons(WuiReportFailuresBase): 381 """ 382 Generates a report displaying the failure reasons over time. 383 """ 384 385 def _formatEdgeOccurenceSubject(self, oTransient): 386 return u'%s / %s' % ( webutils.escapeElem(oTransient.oReason.oCategory.sShort), 387 webutils.escapeElem(oTransient.oReason.sShort),); 388 389 def _formatSeriesNameForTable(self, oSet, idKey): 390 oReason = oSet.dSubjects[idKey]; 391 sHtml = u'<td>'; 392 sHtml += u'%s / %s' % ( webutils.escapeElem(oReason.oCategory.sShort), webutils.escapeElem(oReason.sShort),); 393 sHtml += u'</td>'; 394 return sHtml; 395 396 397 def generateReportBody(self): 398 self._sTitle = 'Failure reasons'; 399 400 # 401 # Get the data and sort the data series in descending order of badness. 402 # 403 oSet = self._oModel.getFailureReasons(); 404 aidSortedRaw = sorted(oSet.dSubjects, key = lambda idReason: oSet.dcHitsPerId[idReason], reverse = True); 405 406 # 407 # Generate table and transition list. These are the most useful ones with the current graph machinery. 408 # 409 sHtml = self._generateTableForSet(oSet, 'Test Cases', aidSortedRaw); 410 sHtml += self._generateTransitionList(oSet); 411 412 # 413 # Check if most of the stuff is without any assign reason, if so, skip 414 # that part of the graph so it doesn't offset the interesting bits. 415 # 416 fIncludeWithoutReason = True; 417 for oPeriod in reversed(oSet.aoPeriods): 418 if oPeriod.cWithoutReason > oSet.cMaxHits * 4: 419 fIncludeWithoutReason = False; 420 sHtml += '<p>Warning: Many failures without assigned reason!</p>\n'; 421 break; 422 423 # 424 # Generate the graph. 425 # 426 fGenerateGraph = len(aidSortedRaw) <= 9 and len(aidSortedRaw) > 0; ## Make this configurable. 427 if fGenerateGraph: 428 aidSorted = aidSortedRaw; 429 430 asNames = []; 431 for idReason in aidSorted: 432 oReason = oSet.dSubjects[idReason]; 433 asNames.append('%s / %s' % (oReason.oCategory.sShort, oReason.sShort,) ) 434 if fIncludeWithoutReason: 435 asNames.append('No reason'); 436 437 oTable = WuiHlpGraphDataTable('Period', asNames); 438 439 cMax = oSet.cMaxHits; 440 for _, oPeriod in enumerate(reversed(oSet.aoPeriods)): 441 aiValues = []; 442 443 for idReason in aidSorted: 444 oRow = oPeriod.dRowsById.get(idReason, None); 445 iValue = oRow.cHits if oRow is not None else 0; 446 aiValues.append(iValue); 447 448 if fIncludeWithoutReason: 449 aiValues.append(oPeriod.cWithoutReason); 450 if oPeriod.cWithoutReason > cMax: 451 cMax = oPeriod.cWithoutReason; 452 453 oTable.addRow(oPeriod.sDesc, aiValues); 454 455 oGraph = WuiHlpBarGraph('failure-reason', oTable, self._oDisp); 456 oGraph.setRangeMax(max(cMax + 1, 3)); 457 sHtml += oGraph.renderGraph(); 458 return sHtml; 459 460 461 class WuiReportTestCaseFailures(WuiReportFailuresWithTotalBase): 462 """ 463 Generates a report displaying the failure reasons over time. 464 """ 465 466 def _formatEdgeOccurenceSubject(self, oTransient): 467 sHtml = u'%s ' % ( webutils.escapeElem(oTransient.oSubject.sName),); 468 sHtml += WuiTestCaseDetailsLink(oTransient.oSubject.idTestCase, fBracketed = False).toHtml(); 469 return sHtml; 470 471 def _formatSeriesNameForTable(self, oSet, idKey): 472 oTestCase = oSet.dSubjects[idKey]; 473 sHtml = u'<td>'; 474 sHtml += WuiReportSummaryLink(ReportModelBase.ksSubTestCase, oTestCase.idTestCase, sName = oTestCase.sName, 475 dExtraParams = self._dExtraParams).toHtml(); 476 sHtml += u' '; 477 sHtml += WuiTestCaseDetailsLink(oTestCase.idTestCase).toHtml(); 478 sHtml += u'</td>'; 479 return sHtml; 480 481 def generateReportBody(self): 482 self._sTitle = 'Test Case Failures'; 483 oSet = self._oModel.getTestCaseFailures(); 484 aidSortedRaw = self._getSortedIds(oSet); 485 486 sHtml = self._generateTableForSet(oSet, 'Test Cases', aidSortedRaw); 487 sHtml += self._generateTransitionList(oSet); 488 sHtml += self._generateGraph(oSet, 'testcase-graph', aidSortedRaw); 489 return sHtml; 490 491 492 class WuiReportTestCaseArgsFailures(WuiReportFailuresWithTotalBase): 493 """ 494 Generates a report displaying the failure reasons over time. 495 """ 496 497 @staticmethod 498 def _formatName(oTestCaseArgs): 499 if oTestCaseArgs.sSubName is not None and len(oTestCaseArgs.sSubName) > 0: 500 sName = u'%s / %s' % ( oTestCaseArgs.oTestCase.sName, oTestCaseArgs.sSubName, ); 501 else: 502 sName = u'%s / #%u' % ( oTestCaseArgs.oTestCase.sName, oTestCaseArgs.idTestCaseArgs, ); 503 return sName; 504 505 def _formatEdgeOccurenceSubject(self, oTransient): 506 sHtml = u'%s ' % ( webutils.escapeElem(self._formatName(oTransient.oSubject)),); 507 sHtml += WuiTestCaseDetailsLink(oTransient.oSubject.idTestCase, fBracketed = False).toHtml(); 508 return sHtml; 509 510 def _formatSeriesNameForTable(self, oSet, idKey): 511 oTestCaseArgs = oSet.dSubjects[idKey]; 512 sHtml = u'<td>'; 513 sHtml += WuiReportSummaryLink(ReportModelBase.ksSubTestCaseArgs, oTestCaseArgs.idTestCaseArgs, 514 sName = self._formatName(oTestCaseArgs), dExtraParams = self._dExtraParams).toHtml(); 515 sHtml += u' '; 516 sHtml += WuiTestCaseDetailsLink(oTestCaseArgs.idTestCase).toHtml(); 517 sHtml += u'</td>'; 518 return sHtml; 519 520 def generateReportBody(self): 521 self._sTitle = 'Test Case Variation Failures'; 522 oSet = self._oModel.getTestCaseVariationFailures(); 523 aidSortedRaw = self._getSortedIds(oSet); 524 525 sHtml = self._generateTableForSet(oSet, 'Test Case Variations', aidSortedRaw); 526 sHtml += self._generateTransitionList(oSet); 527 sHtml += self._generateGraph(oSet, 'testcasearg-graph', aidSortedRaw); 528 return sHtml; 529 530 531 532 class WuiReportTestBoxFailures(WuiReportFailuresWithTotalBase): 533 """ 534 Generates a report displaying the failure reasons over time. 535 """ 536 537 def _formatEdgeOccurenceSubject(self, oTransient): 538 sHtml = u'%s ' % ( webutils.escapeElem(oTransient.oSubject.sName),); 539 sHtml += WuiTestBoxDetailsLink(oTransient.oSubject.idTestBox, fBracketed = False).toHtml(); 540 return sHtml; 541 542 def _formatSeriesNameForTable(self, oSet, idKey): 543 oTestBox = oSet.dSubjects[idKey]; 544 sHtml = u'<td>'; 545 sHtml += WuiReportSummaryLink(ReportModelBase.ksSubTestBox, oTestBox.idTestBox, sName = oTestBox.sName, 546 dExtraParams = self._dExtraParams).toHtml(); 547 sHtml += u' '; 548 sHtml += WuiTestBoxDetailsLink(oTestBox.idTestBox).toHtml(); 549 sHtml += u'</td>'; 550 return sHtml; 551 552 def generateReportBody(self): 553 self._sTitle = 'Test Box Failures'; 554 oSet = self._oModel.getTestBoxFailures(); 555 aidSortedRaw = self._getSortedIds(oSet); 556 557 sHtml = self._generateTableForSet(oSet, 'Test Boxes', aidSortedRaw); 558 sHtml += self._generateTransitionList(oSet); 559 sHtml += self._generateGraph(oSet, 'testbox-graph', aidSortedRaw); 466 560 return sHtml; 467 561 … … 477 571 % (self._oModel.sSubject, self._oModel.aidSubjects,); 478 572 479 oSuccessRate = WuiReportSuccessRate( self._oModel, self._dParams, fSubReport = True, 480 fnDPrint = self._fnDPrint, oDisp = self._oDisp); 481 oTestCaseFailures = WuiReportTestCaseFailures(self._oModel, self._dParams, fSubReport = True, 482 fnDPrint = self._fnDPrint, oDisp = self._oDisp); 483 oFailureReasons = WuiReportFailureReasons( self._oModel, self._dParams, fSubReport = True, 484 fnDPrint = self._fnDPrint, oDisp = self._oDisp); 485 for oReport in [oSuccessRate, oTestCaseFailures, oFailureReasons, ]: 573 aoReports = []; 574 575 aoReports.append(WuiReportSuccessRate( self._oModel, self._dParams, fSubReport = True, 576 fnDPrint = self._fnDPrint, oDisp = self._oDisp)); 577 aoReports.append(WuiReportTestCaseFailures(self._oModel, self._dParams, fSubReport = True, 578 fnDPrint = self._fnDPrint, oDisp = self._oDisp)); 579 if self._oModel.sSubject == ReportModelBase.ksSubTestCase: 580 aoReports.append(WuiReportTestCaseArgsFailures(self._oModel, self._dParams, fSubReport = True, 581 fnDPrint = self._fnDPrint, oDisp = self._oDisp)); 582 aoReports.append(WuiReportTestBoxFailures( self._oModel, self._dParams, fSubReport = True, 583 fnDPrint = self._fnDPrint, oDisp = self._oDisp)); 584 aoReports.append(WuiReportFailureReasons( self._oModel, self._dParams, fSubReport = True, 585 fnDPrint = self._fnDPrint, oDisp = self._oDisp)); 586 587 for oReport in aoReports: 486 588 (sTitle, sContent) = oReport.show(); 487 589 sHtml += '<br>'; # drop this layout hack
Note:
See TracChangeset
for help on using the changeset viewer.