eric7/Unittest/UTTestResultsTree.py

branch
unittest
changeset 9063
f1d7dd7ae471
parent 9062
7f27bf3b50c3
child 9064
339bb8c8007d
equal deleted inserted replaced
9062:7f27bf3b50c3 9063:f1d7dd7ae471
9 """ 9 """
10 10
11 import contextlib 11 import contextlib
12 import copy 12 import copy
13 import locale 13 import locale
14
15 from collections import Counter
14 from operator import attrgetter 16 from operator import attrgetter
15 17
16 from PyQt6.QtCore import ( 18 from PyQt6.QtCore import (
17 pyqtSignal, pyqtSlot, Qt, QAbstractItemModel, QCoreApplication, QModelIndex 19 pyqtSignal, pyqtSlot, Qt, QAbstractItemModel, QCoreApplication, QModelIndex
18 ) 20 )
29 31
30 32
31 class TestResultsModel(QAbstractItemModel): 33 class TestResultsModel(QAbstractItemModel):
32 """ 34 """
33 Class implementing the item model containing the test data. 35 Class implementing the item model containing the test data.
36
37 @signal summary(str) emitted whenever the model data changes. The element
38 is a summary of the test results of the model.
34 """ 39 """
40 summary = pyqtSignal(str)
41
35 Headers = [ 42 Headers = [
36 QCoreApplication.translate("TestResultsModel", "Status"), 43 QCoreApplication.translate("TestResultsModel", "Status"),
37 QCoreApplication.translate("TestResultsModel", "Name"), 44 QCoreApplication.translate("TestResultsModel", "Name"),
38 QCoreApplication.translate("TestResultsModel", "Message"), 45 QCoreApplication.translate("TestResultsModel", "Message"),
39 QCoreApplication.translate("TestResultsModel", "Duration (ms)"), 46 QCoreApplication.translate("TestResultsModel", "Duration (ms)"),
127 elif column == TestResultsModel.MessageColumn: 134 elif column == TestResultsModel.MessageColumn:
128 return self.__testResults[row].message 135 return self.__testResults[row].message
129 elif column == TestResultsModel.DurationColumn: 136 elif column == TestResultsModel.DurationColumn:
130 duration = self.__testResults[row].duration 137 duration = self.__testResults[row].duration
131 return ( 138 return (
132 '' 139 ""
133 if duration is None else 140 if duration is None else
134 locale.format_string("%.2f", duration, grouping=True) 141 locale.format_string("%.2f", duration, grouping=True)
135 ) 142 )
136 elif role == Qt.ItemDataRole.ToolTipRole: 143 elif role == Qt.ItemDataRole.ToolTipRole:
137 if idx == TopLevelId and column == TestResultsModel.NameColumn: 144 if idx == TopLevelId and column == TestResultsModel.NameColumn:
287 @type list of UTTestResult 294 @type list of UTTestResult
288 """ 295 """
289 self.beginResetModel() 296 self.beginResetModel()
290 self.__testResults = copy.deepcopy(testResults) 297 self.__testResults = copy.deepcopy(testResults)
291 self.endResetModel() 298 self.endResetModel()
299
300 self.summary.emit(self.__summary())
292 301
293 def addTestResults(self, testResults): 302 def addTestResults(self, testResults):
294 """ 303 """
295 Public method to add test results to the ones already managed by the 304 Public method to add test results to the ones already managed by the
296 model. 305 model.
301 firstRow = len(self.__testResults) 310 firstRow = len(self.__testResults)
302 lastRow = firstRow + len(testResults) - 1 311 lastRow = firstRow + len(testResults) - 1
303 self.beginInsertRows(QModelIndex(), firstRow, lastRow) 312 self.beginInsertRows(QModelIndex(), firstRow, lastRow)
304 self.__testResults.extend(testResults) 313 self.__testResults.extend(testResults)
305 self.endInsertRows() 314 self.endInsertRows()
315
316 self.summary.emit(self.__summary())
306 317
307 def updateTestResults(self, testResults): 318 def updateTestResults(self, testResults):
308 """ 319 """
309 Public method to update the data of managed test result items. 320 Public method to update the data of managed test result items.
310 321
311 @param testResults test results to be updated 322 @param testResults test results to be updated
312 @type list of UTTestResult 323 @type list of UTTestResult
313 """ 324 """
314 minIndex = None 325 minIndex = None
315 maxIndex = None 326 maxIndex = None
327
328 testResultsToBeAdded = []
316 329
317 for testResult in testResults: 330 for testResult in testResults:
318 for (index, currentResult) in enumerate(self.__testResults): 331 for (index, currentResult) in enumerate(self.__testResults):
319 if currentResult.id == testResult.id: 332 if currentResult.id == testResult.id:
320 self.__testResults[index] = testResult 333 self.__testResults[index] = testResult
322 minIndex = index 335 minIndex = index
323 maxIndex = index 336 maxIndex = index
324 else: 337 else:
325 minIndex = min(minIndex, index) 338 minIndex = min(minIndex, index)
326 maxIndex = max(maxIndex, index) 339 maxIndex = max(maxIndex, index)
340
341 break
342 else:
343 # Test result with given id was not found.
344 # Just add it to the list (could be a sub test)
345 testResultsToBeAdded.append(testResult)
327 346
328 if minIndex is not None: 347 if minIndex is not None:
329 self.dataChanged.emit( 348 self.dataChanged.emit(
330 self.index(minIndex, 0), 349 self.index(minIndex, 0),
331 self.index(maxIndex, len(TestResultsModel.Headers) - 1) 350 self.index(maxIndex, len(TestResultsModel.Headers) - 1)
332 ) 351 )
352
353 self.summary.emit(self.__summary())
354
355 if testResultsToBeAdded:
356 self.addTestResults(testResultsToBeAdded)
357
358 def __summary(self):
359 """
360 Private method to generate a test results summary text.
361
362 @return test results summary text
363 @rtype str
364 """
365 if len(self.__testResults) == 0:
366 return self.tr("No results to show")
367
368 counts = Counter(res.category for res in self.__testResults)
369 if all(
370 counts[category] == 0
371 for category in (ResultCategory.FAIL, ResultCategory.OK,
372 ResultCategory.SKIP)
373 ):
374 return self.tr("Collected %n test(s)", "", len(self.__testResults))
375
376 return self.tr(
377 "%n test(s)/subtest(s) total, {0} failed, {1} passed,"
378 " {2} skipped, {3} pending",
379 "", len(self.__testResults)
380 ).format(
381 counts[ResultCategory.FAIL],
382 counts[ResultCategory.OK],
383 counts[ResultCategory.SKIP],
384 counts[ResultCategory.PENDING]
385 )
333 386
334 387
335 class TestResultsTreeView(QTreeView): 388 class TestResultsTreeView(QTreeView):
336 """ 389 """
337 Class implementing a tree view to show the test result data. 390 Class implementing a tree view to show the test result data.

eric ide

mercurial