19 from PyQt6.QtWidgets import ( |
19 from PyQt6.QtWidgets import ( |
20 QWidget, QDialog, QApplication, QDialogButtonBox, QListWidgetItem, |
20 QWidget, QDialog, QApplication, QDialogButtonBox, QListWidgetItem, |
21 QComboBox, QTreeWidgetItem |
21 QComboBox, QTreeWidgetItem |
22 ) |
22 ) |
23 |
23 |
24 from E5Gui.E5Application import e5App |
24 from E5Gui.EricApplication import ericApp |
25 from E5Gui import E5MessageBox |
25 from E5Gui import EricMessageBox |
26 from E5Gui.E5MainWindow import E5MainWindow |
26 from E5Gui.EricMainWindow import EricMainWindow |
27 from E5Gui.E5PathPicker import E5PathPickerModes |
27 from E5Gui.EricPathPicker import EricPathPickerModes |
28 |
28 |
29 from .Ui_UnittestDialog import Ui_UnittestDialog |
29 from .Ui_UnittestDialog import Ui_UnittestDialog |
30 |
30 |
31 import UI.PixmapCache |
31 import UI.PixmapCache |
32 |
32 |
75 super().__init__(parent) |
75 super().__init__(parent) |
76 if name: |
76 if name: |
77 self.setObjectName(name) |
77 self.setObjectName(name) |
78 self.setupUi(self) |
78 self.setupUi(self) |
79 |
79 |
80 self.testsuitePicker.setMode(E5PathPickerModes.OPEN_FILE_MODE) |
80 self.testsuitePicker.setMode(EricPathPickerModes.OPEN_FILE_MODE) |
81 self.testsuitePicker.setInsertPolicy( |
81 self.testsuitePicker.setInsertPolicy( |
82 QComboBox.InsertPolicy.InsertAtTop) |
82 QComboBox.InsertPolicy.InsertAtTop) |
83 self.testsuitePicker.setSizeAdjustPolicy( |
83 self.testsuitePicker.setSizeAdjustPolicy( |
84 QComboBox.SizeAdjustPolicy.AdjustToMinimumContentsLengthWithIcon) |
84 QComboBox.SizeAdjustPolicy.AdjustToMinimumContentsLengthWithIcon) |
85 |
85 |
86 self.discoveryPicker.setMode(E5PathPickerModes.DIRECTORY_MODE) |
86 self.discoveryPicker.setMode(EricPathPickerModes.DIRECTORY_MODE) |
87 self.discoveryPicker.setInsertPolicy( |
87 self.discoveryPicker.setInsertPolicy( |
88 QComboBox.InsertPolicy.InsertAtTop) |
88 QComboBox.InsertPolicy.InsertAtTop) |
89 self.discoveryPicker.setSizeAdjustPolicy( |
89 self.discoveryPicker.setSizeAdjustPolicy( |
90 QComboBox.SizeAdjustPolicy.AdjustToMinimumContentsLengthWithIcon) |
90 QComboBox.SizeAdjustPolicy.AdjustToMinimumContentsLengthWithIcon) |
91 |
91 |
136 |
136 |
137 self.debuggerCheckBox.setChecked(True) |
137 self.debuggerCheckBox.setChecked(True) |
138 |
138 |
139 # virtual environment manager is only used in the integrated |
139 # virtual environment manager is only used in the integrated |
140 # variant |
140 # variant |
141 self.__venvManager = e5App().getObject("VirtualEnvManager") |
141 self.__venvManager = ericApp().getObject("VirtualEnvManager") |
142 self.__populateVenvComboBox() |
142 self.__populateVenvComboBox() |
143 self.__venvManager.virtualEnvironmentAdded.connect( |
143 self.__venvManager.virtualEnvironmentAdded.connect( |
144 self.__populateVenvComboBox) |
144 self.__populateVenvComboBox) |
145 self.__venvManager.virtualEnvironmentRemoved.connect( |
145 self.__venvManager.virtualEnvironmentRemoved.connect( |
146 self.__populateVenvComboBox) |
146 self.__populateVenvComboBox) |
230 @param forProject flag indicating to run for the open project |
230 @param forProject flag indicating to run for the open project |
231 @type bool |
231 @type bool |
232 """ |
232 """ |
233 self.__forProject = forProject |
233 self.__forProject = forProject |
234 if forProject: |
234 if forProject: |
235 project = e5App().getObject("Project") |
235 project = ericApp().getObject("Project") |
236 if project.isOpen(): |
236 if project.isOpen(): |
237 self.insertDiscovery(project.getProjectPath()) |
237 self.insertDiscovery(project.getProjectPath()) |
238 else: |
238 else: |
239 self.insertDiscovery("") |
239 self.insertDiscovery("") |
240 else: |
240 else: |
310 |
310 |
311 defaultDirectory = Preferences.getMultiProject("Workspace") |
311 defaultDirectory = Preferences.getMultiProject("Workspace") |
312 if not defaultDirectory: |
312 if not defaultDirectory: |
313 defaultDirectory = os.path.expanduser("~") |
313 defaultDirectory = os.path.expanduser("~") |
314 if self.__dbs: |
314 if self.__dbs: |
315 project = e5App().getObject("Project") |
315 project = ericApp().getObject("Project") |
316 if self.__forProject and project.isOpen(): |
316 if self.__forProject and project.isOpen(): |
317 defaultDirectory = project.getProjectPath() |
317 defaultDirectory = project.getProjectPath() |
318 self.testsuitePicker.setDefaultDirectory(defaultDirectory) |
318 self.testsuitePicker.setDefaultDirectory(defaultDirectory) |
319 |
319 |
320 @pyqtSlot(str) |
320 @pyqtSlot(str) |
348 self.discoverButton.setEnabled(checked) |
348 self.discoverButton.setEnabled(checked) |
349 self.discoveryList.clear() |
349 self.discoveryList.clear() |
350 |
350 |
351 if not bool(self.discoveryPicker.currentText()): |
351 if not bool(self.discoveryPicker.currentText()): |
352 if self.__forProject: |
352 if self.__forProject: |
353 project = e5App().getObject("Project") |
353 project = ericApp().getObject("Project") |
354 if project.isOpen(): |
354 if project.isOpen(): |
355 self.insertDiscovery(project.getProjectPath()) |
355 self.insertDiscovery(project.getProjectPath()) |
356 return |
356 return |
357 |
357 |
358 self.insertDiscovery(Preferences.getMultiProject("Workspace")) |
358 self.insertDiscovery(Preferences.getMultiProject("Workspace")) |
389 self.testName = self.tr("Unittest with auto-discovery") |
389 self.testName = self.tr("Unittest with auto-discovery") |
390 if self.__dbs: |
390 if self.__dbs: |
391 venvName = self.venvComboBox.currentText() |
391 venvName = self.venvComboBox.currentText() |
392 |
392 |
393 # we are cooperating with the eric IDE |
393 # we are cooperating with the eric IDE |
394 project = e5App().getObject("Project") |
394 project = ericApp().getObject("Project") |
395 if self.__forProject: |
395 if self.__forProject: |
396 mainScript = project.getMainScript(True) |
396 mainScript = project.getMainScript(True) |
397 clientType = project.getProjectLanguage() |
397 clientType = project.getProjectLanguage() |
398 if mainScript: |
398 if mainScript: |
399 workdir = os.path.dirname(os.path.abspath(mainScript)) |
399 workdir = os.path.dirname(os.path.abspath(mainScript)) |
402 sysPath = [workdir] |
402 sysPath = [workdir] |
403 if not discoveryStart: |
403 if not discoveryStart: |
404 discoveryStart = workdir |
404 discoveryStart = workdir |
405 else: |
405 else: |
406 if not discoveryStart: |
406 if not discoveryStart: |
407 E5MessageBox.critical( |
407 EricMessageBox.critical( |
408 self, |
408 self, |
409 self.tr("Unittest"), |
409 self.tr("Unittest"), |
410 self.tr("You must enter a start directory for" |
410 self.tr("You must enter a start directory for" |
411 " auto-discovery.")) |
411 " auto-discovery.")) |
412 return |
412 return |
418 venvName, sysPath, workdir, |
418 venvName, sysPath, workdir, |
419 discoveryStart) |
419 discoveryStart) |
420 else: |
420 else: |
421 # we are running as an application |
421 # we are running as an application |
422 if not discoveryStart: |
422 if not discoveryStart: |
423 E5MessageBox.critical( |
423 EricMessageBox.critical( |
424 self, |
424 self, |
425 self.tr("Unittest"), |
425 self.tr("Unittest"), |
426 self.tr("You must enter a start directory for" |
426 self.tr("You must enter a start directory for" |
427 " auto-discovery.")) |
427 " auto-discovery.")) |
428 return |
428 return |
446 os.chdir(discoveryStart) |
446 os.chdir(discoveryStart) |
447 try: |
447 try: |
448 testLoader = unittest.TestLoader() |
448 testLoader = unittest.TestLoader() |
449 test = testLoader.discover(discoveryStart) |
449 test = testLoader.discover(discoveryStart) |
450 if hasattr(testLoader, "errors") and bool(testLoader.errors): |
450 if hasattr(testLoader, "errors") and bool(testLoader.errors): |
451 E5MessageBox.critical( |
451 EricMessageBox.critical( |
452 self, |
452 self, |
453 self.tr("Unittest"), |
453 self.tr("Unittest"), |
454 self.tr( |
454 self.tr( |
455 "<p>Unable to discover tests.</p>" |
455 "<p>Unable to discover tests.</p>" |
456 "<p>{0}</p>" |
456 "<p>{0}</p>" |
466 self.tr("Discovered %n Test(s)", "", |
466 self.tr("Discovered %n Test(s)", "", |
467 len(testsList))) |
467 len(testsList))) |
468 self.tabWidget.setCurrentIndex(0) |
468 self.tabWidget.setCurrentIndex(0) |
469 except Exception: |
469 except Exception: |
470 exc_type, exc_value, exc_tb = sys.exc_info() |
470 exc_type, exc_value, exc_tb = sys.exc_info() |
471 E5MessageBox.critical( |
471 EricMessageBox.critical( |
472 self, |
472 self, |
473 self.tr("Unittest"), |
473 self.tr("Unittest"), |
474 self.tr( |
474 self.tr( |
475 "<p>Unable to discover tests.</p>" |
475 "<p>Unable to discover tests.</p>" |
476 "<p>{0}<br/>{1}</p>") |
476 "<p>{0}<br/>{1}</p>") |
622 self.sbLabel.setText( |
622 self.sbLabel.setText( |
623 self.tr("Discovered %n Test(s)", "", |
623 self.tr("Discovered %n Test(s)", "", |
624 len(testCases))) |
624 len(testCases))) |
625 self.tabWidget.setCurrentIndex(0) |
625 self.tabWidget.setCurrentIndex(0) |
626 else: |
626 else: |
627 E5MessageBox.critical( |
627 EricMessageBox.critical( |
628 self, |
628 self, |
629 self.tr("Unittest"), |
629 self.tr("Unittest"), |
630 self.tr("<p>Unable to discover tests.</p>" |
630 self.tr("<p>Unable to discover tests.</p>" |
631 "<p>{0}<br/>{1}</p>") |
631 "<p>{0}<br/>{1}</p>") |
632 .format(exc_type, exc_value.replace("\n", "<br/>")) |
632 .format(exc_type, exc_value.replace("\n", "<br/>")) |
688 self.insertTestName(testName) |
688 self.insertTestName(testName) |
689 if testFileName and not testName: |
689 if testFileName and not testName: |
690 testName = "suite" |
690 testName = "suite" |
691 |
691 |
692 if not discover and not testFileName and not testName: |
692 if not discover and not testFileName and not testName: |
693 E5MessageBox.critical( |
693 EricMessageBox.critical( |
694 self, |
694 self, |
695 self.tr("Unittest"), |
695 self.tr("Unittest"), |
696 self.tr("You must select auto-discovery or enter a test suite" |
696 self.tr("You must select auto-discovery or enter a test suite" |
697 " file or a dotted test name.")) |
697 " file or a dotted test name.")) |
698 return |
698 return |
718 testCases = [] |
718 testCases = [] |
719 else: |
719 else: |
720 testCases = self.__selectedTestCases() |
720 testCases = self.__selectedTestCases() |
721 |
721 |
722 if not testCases and self.discoveryList.topLevelItemCount(): |
722 if not testCases and self.discoveryList.topLevelItemCount(): |
723 ok = E5MessageBox.yesNo( |
723 ok = EricMessageBox.yesNo( |
724 self, |
724 self, |
725 self.tr("Unittest"), |
725 self.tr("Unittest"), |
726 self.tr("""No test case has been selected. Shall all""" |
726 self.tr("""No test case has been selected. Shall all""" |
727 """ test cases be run?""")) |
727 """ test cases be run?""")) |
728 if not ok: |
728 if not ok: |
730 |
730 |
731 if self.__dbs: |
731 if self.__dbs: |
732 venvName = self.venvComboBox.currentText() |
732 venvName = self.venvComboBox.currentText() |
733 |
733 |
734 # we are cooperating with the eric IDE |
734 # we are cooperating with the eric IDE |
735 project = e5App().getObject("Project") |
735 project = ericApp().getObject("Project") |
736 if self.__forProject: |
736 if self.__forProject: |
737 mainScript = project.getMainScript(True) |
737 mainScript = project.getMainScript(True) |
738 clientType = project.getProjectLanguage() |
738 clientType = project.getProjectLanguage() |
739 if mainScript: |
739 if mainScript: |
740 workdir = os.path.dirname(os.path.abspath(mainScript)) |
740 workdir = os.path.dirname(os.path.abspath(mainScript)) |
746 if discover and not discoveryStart: |
746 if discover and not discoveryStart: |
747 discoveryStart = workdir |
747 discoveryStart = workdir |
748 else: |
748 else: |
749 if discover: |
749 if discover: |
750 if not discoveryStart: |
750 if not discoveryStart: |
751 E5MessageBox.critical( |
751 EricMessageBox.critical( |
752 self, |
752 self, |
753 self.tr("Unittest"), |
753 self.tr("Unittest"), |
754 self.tr("You must enter a start directory for" |
754 self.tr("You must enter a start directory for" |
755 " auto-discovery.")) |
755 " auto-discovery.")) |
756 return |
756 return |
785 discover=discover, discoveryStart=discoveryStart, |
785 discover=discover, discoveryStart=discoveryStart, |
786 testCases=testCases, debug=self.debuggerCheckBox.isChecked()) |
786 testCases=testCases, debug=self.debuggerCheckBox.isChecked()) |
787 else: |
787 else: |
788 # we are running as an application |
788 # we are running as an application |
789 if discover and not discoveryStart: |
789 if discover and not discoveryStart: |
790 E5MessageBox.critical( |
790 EricMessageBox.critical( |
791 self, |
791 self, |
792 self.tr("Unittest"), |
792 self.tr("Unittest"), |
793 self.tr("You must enter a start directory for" |
793 self.tr("You must enter a start directory for" |
794 " auto-discovery.")) |
794 " auto-discovery.")) |
795 return |
795 return |
847 else: |
847 else: |
848 test = testLoader.loadTestsFromName( |
848 test = testLoader.loadTestsFromName( |
849 testName, module) |
849 testName, module) |
850 except Exception: |
850 except Exception: |
851 exc_type, exc_value, exc_tb = sys.exc_info() |
851 exc_type, exc_value, exc_tb = sys.exc_info() |
852 E5MessageBox.critical( |
852 EricMessageBox.critical( |
853 self, |
853 self, |
854 self.tr("Unittest"), |
854 self.tr("Unittest"), |
855 self.tr( |
855 self.tr( |
856 "<p>Unable to run test <b>{0}</b>.</p>" |
856 "<p>Unable to run test <b>{0}</b>.</p>" |
857 "<p>{1}<br/>{2}</p>") |
857 "<p>{1}<br/>{2}</p>") |
879 |
879 |
880 self.testResult = QtTestResult( |
880 self.testResult = QtTestResult( |
881 self, self.failfastCheckBox.isChecked()) |
881 self, self.failfastCheckBox.isChecked()) |
882 self.totalTests = test.countTestCases() |
882 self.totalTests = test.countTestCases() |
883 if self.totalTests == 0: |
883 if self.totalTests == 0: |
884 E5MessageBox.warning( |
884 EricMessageBox.warning( |
885 self, |
885 self, |
886 self.tr("Unittest"), |
886 self.tr("Unittest"), |
887 self.tr("""No unittest were found. Aborting...""")) |
887 self.tr("""No unittest were found. Aborting...""")) |
888 else: |
888 else: |
889 self.__failedTests = [] |
889 self.__failedTests = [] |
907 @param nrTests number of tests contained in the test suite (integer) |
907 @param nrTests number of tests contained in the test suite (integer) |
908 @param exc_type type of exception occured during preparation (string) |
908 @param exc_type type of exception occured during preparation (string) |
909 @param exc_value value of exception occured during preparation (string) |
909 @param exc_value value of exception occured during preparation (string) |
910 """ |
910 """ |
911 if nrTests == 0: |
911 if nrTests == 0: |
912 E5MessageBox.critical( |
912 EricMessageBox.critical( |
913 self, |
913 self, |
914 self.tr("Unittest"), |
914 self.tr("Unittest"), |
915 self.tr( |
915 self.tr( |
916 "<p>Unable to run test <b>{0}</b>.</p>" |
916 "<p>Unable to run test <b>{0}</b>.</p>" |
917 "<p>{1}<br/>{2}</p>") |
917 "<p>{1}<br/>{2}</p>") |
1064 @param testId id of the test (string) |
1064 @param testId id of the test (string) |
1065 """ |
1065 """ |
1066 self.skippedCount += 1 |
1066 self.skippedCount += 1 |
1067 self.progressCounterSkippedCount.setText(str(self.skippedCount)) |
1067 self.progressCounterSkippedCount.setText(str(self.skippedCount)) |
1068 itm = QListWidgetItem(self.tr(" Skipped: {0}").format(reason)) |
1068 itm = QListWidgetItem(self.tr(" Skipped: {0}").format(reason)) |
1069 if e5App().usesDarkPalette(): |
1069 if ericApp().usesDarkPalette(): |
1070 itm.setForeground(self.SkippedColorDarkTheme) |
1070 itm.setForeground(self.SkippedColorDarkTheme) |
1071 else: |
1071 else: |
1072 itm.setForeground(self.SkippedColorLightTheme) |
1072 itm.setForeground(self.SkippedColorLightTheme) |
1073 self.testsListWidget.insertItem(1, itm) |
1073 self.testsListWidget.insertItem(1, itm) |
1074 |
1074 |
1082 """ |
1082 """ |
1083 self.expectedFailureCount += 1 |
1083 self.expectedFailureCount += 1 |
1084 self.progressCounterExpectedFailureCount.setText( |
1084 self.progressCounterExpectedFailureCount.setText( |
1085 str(self.expectedFailureCount)) |
1085 str(self.expectedFailureCount)) |
1086 itm = QListWidgetItem(self.tr(" Expected Failure")) |
1086 itm = QListWidgetItem(self.tr(" Expected Failure")) |
1087 if e5App().usesDarkPalette(): |
1087 if ericApp().usesDarkPalette(): |
1088 itm.setForeground(self.FailedExpectedColorDarkTheme) |
1088 itm.setForeground(self.FailedExpectedColorDarkTheme) |
1089 else: |
1089 else: |
1090 itm.setForeground(self.FailedExpectedColorLightTheme) |
1090 itm.setForeground(self.FailedExpectedColorLightTheme) |
1091 self.testsListWidget.insertItem(1, itm) |
1091 self.testsListWidget.insertItem(1, itm) |
1092 |
1092 |
1099 """ |
1099 """ |
1100 self.unexpectedSuccessCount += 1 |
1100 self.unexpectedSuccessCount += 1 |
1101 self.progressCounterUnexpectedSuccessCount.setText( |
1101 self.progressCounterUnexpectedSuccessCount.setText( |
1102 str(self.unexpectedSuccessCount)) |
1102 str(self.unexpectedSuccessCount)) |
1103 itm = QListWidgetItem(self.tr(" Unexpected Success")) |
1103 itm = QListWidgetItem(self.tr(" Unexpected Success")) |
1104 if e5App().usesDarkPalette(): |
1104 if ericApp().usesDarkPalette(): |
1105 itm.setForeground(self.SucceededUnexpectedColorDarkTheme) |
1105 itm.setForeground(self.SucceededUnexpectedColorDarkTheme) |
1106 else: |
1106 else: |
1107 itm.setForeground(self.SucceededUnexpectedColorLightTheme) |
1107 itm.setForeground(self.SucceededUnexpectedColorLightTheme) |
1108 self.testsListWidget.insertItem(1, itm) |
1108 self.testsListWidget.insertItem(1, itm) |
1109 |
1109 |
1328 """ |
1328 """ |
1329 super().stopTest(test) |
1329 super().stopTest(test) |
1330 self.parent.testFinished() |
1330 self.parent.testFinished() |
1331 |
1331 |
1332 |
1332 |
1333 class UnittestWindow(E5MainWindow): |
1333 class UnittestWindow(EricMainWindow): |
1334 """ |
1334 """ |
1335 Main window class for the standalone dialog. |
1335 Main window class for the standalone dialog. |
1336 """ |
1336 """ |
1337 def __init__(self, prog=None, parent=None): |
1337 def __init__(self, prog=None, parent=None): |
1338 """ |
1338 """ |