PyUnit/UnittestDialog.py

changeset 6908
a56b500d7d2d
parent 6905
889339ffe6cf
--- a/PyUnit/UnittestDialog.py	Sat Mar 30 14:16:34 2019 +0100
+++ b/PyUnit/UnittestDialog.py	Sat Mar 30 14:20:29 2019 +0100
@@ -37,13 +37,18 @@
     """
     Class implementing the UI to the pyunit package.
     
-    @signal unittestFile(str, int, int) emitted to show the source of a
+    @signal unittestFile(str, int, bool) emitted to show the source of a
         unittest file
     @signal unittestStopped() emitted after a unit test was run
     """
-    unittestFile = pyqtSignal(str, int, int)
+    unittestFile = pyqtSignal(str, int, bool)
     unittestStopped = pyqtSignal()
     
+    TestCaseNameRole = Qt.UserRole
+    TestCaseFileRole = Qt.UserRole + 1
+    
+    ErrorsInfoRole = Qt.UserRole
+    
     def __init__(self, prog=None, dbs=None, ui=None, parent=None, name=None):
         """
         Constructor
@@ -449,7 +454,8 @@
                     )
                     self.sbLabel.clear()
                 else:
-                    testsList = self.__assembleTestCasesList(test)
+                    testsList = self.__assembleTestCasesList(
+                        test, discoveryStart)
                     self.__populateDiscoveryResults(testsList)
                     self.sbLabel.setText(
                         self.tr("Discovered %n Test(s)", "",
@@ -470,27 +476,34 @@
             
             sys.path = self.savedSysPath
     
-    def __assembleTestCasesList(self, suite):
+    def __assembleTestCasesList(self, suite, start):
         """
         Private method to assemble a list of test cases included in a test
         suite.
         
         @param suite test suite to be inspected
         @type unittest.TestSuite
-        @return list of tuples containing the test case ID and short
-            description
-        @rtype list of tuples of (str, str)
+        @param start name of directory discovery was started at
+        @type str
+        @return list of tuples containing the test case ID, a short description
+            and the path of the test file name
+        @rtype list of tuples of (str, str, str)
         """
         testCases = []
         for test in suite:
             if isinstance(test, unittest.TestSuite):
-                testCases.extend(self.__assembleTestCasesList(test))
+                testCases.extend(self.__assembleTestCasesList(test, start))
             else:
                 testId = test.id()
                 if "ModuleImportFailure" not in testId and \
                    "LoadTestsFailure" not in testId and \
                    "_FailedTest" not in testId:
-                    testCases.append((test.id(), test.shortDescription()))
+                    filename = os.path.join(
+                        start,
+                        test.__module__.replace(".", os.sep) + ".py")
+                    testCases.append(
+                        (test.id(), test.shortDescription(), filename)
+                    )
         return testCases
     
     def __findDiscoveryItem(self, modulePath):
@@ -504,7 +517,7 @@
         """
         itm = self.discoveryList.topLevelItem(0)
         while itm is not None:
-            if itm.data(0, Qt.UserRole) == modulePath:
+            if itm.data(0, UnittestDialog.TestCaseNameRole) == modulePath:
                 return itm
             itm = self.discoveryList.itemBelow(itm)
         
@@ -515,9 +528,9 @@
         Private method to populate the test discovery results list.
         
         @param tests list of tuples containing the discovery results
-        @type list of tuples of (str, str)
+        @type list of tuples of (str, str, str)
         """
-        for test, _testDescription in tests:
+        for test, _testDescription, filename in tests:
             testPath = test.split(".")
             pitm = None
             for index in range(1, len(testPath) + 1):
@@ -535,7 +548,15 @@
                         pitm.setExpanded(True)
                     itm.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
                     itm.setCheckState(0, Qt.Unchecked)
-                    itm.setData(0, Qt.UserRole, modulePath)
+                    itm.setData(0, UnittestDialog.TestCaseNameRole, modulePath)
+                    if os.path.splitext(os.path.basename(filename))[0] == \
+                            itm.text(0):
+                        itm.setData(0, UnittestDialog.TestCaseFileRole,
+                                    filename)
+                    elif pitm:
+                        fn = pitm.data(0, UnittestDialog.TestCaseFileRole)
+                        if fn:
+                            itm.setData(0, UnittestDialog.TestCaseFileRole, fn)
                     pitm = itm
     
     def __selectedTestCases(self, parent=None):
@@ -553,7 +574,8 @@
             for index in range(self.discoveryList.topLevelItemCount()):
                 itm = self.discoveryList.topLevelItem(index)
                 if itm.checkState(0) == Qt.Checked:
-                    selectedTests.append(itm.data(0, Qt.UserRole))
+                    selectedTests.append(
+                        itm.data(0, UnittestDialog.TestCaseNameRole))
                     # ignore children because they are included implicitly
                 elif itm.childCount():
                     # recursively check children
@@ -564,7 +586,8 @@
             for index in range(parent.childCount()):
                 itm = parent.child(index)
                 if itm.checkState(0) == Qt.Checked:
-                    selectedTests.append(itm.data(0, Qt.UserRole))
+                    selectedTests.append(
+                        itm.data(0, UnittestDialog.TestCaseNameRole))
                     # ignore children because they are included implicitly
                 elif itm.childCount():
                     # recursively check children
@@ -601,6 +624,25 @@
                 .format(exc_type, exc_value.replace("\n", "<br/>"))
             )
     
+    @pyqtSlot(QTreeWidgetItem, int)
+    def on_discoveryList_itemDoubleClicked(self, item, column):
+        """
+        Private slot handling the user double clicking an item.
+        
+        @param item reference to the item
+        @type QTreeWidgetItem
+        @param column column of the double click
+        @type int
+        """
+        if item:
+            filename = item.data(0, UnittestDialog.TestCaseFileRole)
+            if filename:
+                if self.__dbs:
+                    # running as part of eric IDE
+                    self.unittestFile.emit(filename, 1, False)
+                else:
+                    self.__openEditor(filename, 1)
+    
     @pyqtSlot()
     def startTests(self, failedOnly=False):
         """
@@ -655,6 +697,15 @@
         else:
             testCases = self.__selectedTestCases()
         
+            if not testCases and self.discoveryList.topLevelItemCount():
+                ok = E5MessageBox.yesNo(
+                    self,
+                    self.tr("Unittest"),
+                    self.tr("""No test case has been selected. Shall all"""
+                            """ test cases be run?"""))
+                if not ok:
+                    return
+        
         if self.__dbs:
             venvName = self.venvComboBox.currentText()
             
@@ -968,7 +1019,7 @@
         self.failCount += 1
         self.progressCounterFailureCount.setText(str(self.failCount))
         itm = QListWidgetItem(self.tr("Failure: {0}").format(test))
-        itm.setData(Qt.UserRole, (test, exc))
+        itm.setData(UnittestDialog.ErrorsInfoRole, (test, exc))
         self.errorsListWidget.insertItem(0, itm)
         self.__failedTests.append(testId)
     
@@ -983,7 +1034,7 @@
         self.errorCount += 1
         self.progressCounterErrorCount.setText(str(self.errorCount))
         itm = QListWidgetItem(self.tr("Error: {0}").format(test))
-        itm.setData(Qt.UserRole, (test, exc))
+        itm.setData(UnittestDialog.ErrorsInfoRole, (test, exc))
         self.errorsListWidget.insertItem(0, itm)
         self.__failedTests.append(testId)
     
@@ -1078,7 +1129,7 @@
         self.on_errorsListWidget_currentTextChanged(text)
         
         # get the error info
-        test, tracebackText = lbitem.data(Qt.UserRole)
+        test, tracebackText = lbitem.data(UnittestDialog.ErrorsInfoRole)
         
         # now build the dialog
         from .Ui_UnittestStacktraceDialog import Ui_UnittestStacktraceDialog
@@ -1117,7 +1168,7 @@
             fn, ln = fmatch.group(1, 2)
             if self.__dbs:
                 # running as part of eric IDE
-                self.unittestFile.emit(fn, int(ln), 1)
+                self.unittestFile.emit(fn, int(ln), True)
             else:
                 self.__openEditor(fn, int(ln))
     

eric ide

mercurial