|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2022 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing a widget to orchestrate unit test execution. |
|
8 """ |
|
9 |
|
10 import enum |
|
11 import os |
|
12 |
|
13 from PyQt6.QtCore import pyqtSlot, Qt, QEvent, QCoreApplication |
|
14 from PyQt6.QtWidgets import ( |
|
15 QAbstractButton, QComboBox, QDialogButtonBox, QWidget |
|
16 ) |
|
17 |
|
18 from EricWidgets import EricMessageBox |
|
19 from EricWidgets.EricApplication import ericApp |
|
20 from EricWidgets.EricMainWindow import EricMainWindow |
|
21 from EricWidgets.EricPathPicker import EricPathPickerModes |
|
22 |
|
23 from .Ui_UnittestWidget import Ui_UnittestWidget |
|
24 |
|
25 from .UTTestResultsTree import TestResultsModel, TestResultsTreeView |
|
26 from .Interfaces import Frameworks |
|
27 from .Interfaces.UTExecutorBase import UTTestConfig, UTTestResult |
|
28 from .Interfaces.UTFrameworkRegistry import UTFrameworkRegistry |
|
29 |
|
30 import Preferences |
|
31 import UI.PixmapCache |
|
32 |
|
33 from Globals import ( |
|
34 recentNameUnittestDiscoverHistory, recentNameUnittestFileHistory, |
|
35 recentNameUnittestTestnameHistory, recentNameUnittestFramework, |
|
36 recentNameUnittestEnvironment |
|
37 ) |
|
38 |
|
39 |
|
40 class UnittestWidgetModes(enum.Enum): |
|
41 """ |
|
42 Class defining the various modes of the unittest widget. |
|
43 """ |
|
44 IDLE = 0 # idle, no test were run yet |
|
45 RUNNING = 1 # test run being performed |
|
46 STOPPED = 2 # test run finished |
|
47 |
|
48 |
|
49 class UnittestWidget(QWidget, Ui_UnittestWidget): |
|
50 """ |
|
51 Class implementing a widget to orchestrate unit test execution. |
|
52 """ |
|
53 def __init__(self, testfile=None, parent=None): |
|
54 """ |
|
55 Constructor |
|
56 |
|
57 @param testfile file name of the test to load |
|
58 @type str |
|
59 @param parent reference to the parent widget (defaults to None) |
|
60 @type QWidget (optional) |
|
61 """ |
|
62 super().__init__(parent) |
|
63 self.setupUi(self) |
|
64 |
|
65 self.__resultsModel = TestResultsModel(self) |
|
66 self.__resultsTree = TestResultsTreeView(self) |
|
67 self.__resultsTree.setModel(self.__resultsModel) |
|
68 self.resultsGroupBox.layout().addWidget(self.__resultsTree) |
|
69 |
|
70 self.versionsButton.setIcon( |
|
71 UI.PixmapCache.getIcon("info")) |
|
72 self.clearHistoriesButton.setIcon( |
|
73 UI.PixmapCache.getIcon("clearPrivateData")) |
|
74 |
|
75 self.testsuitePicker.setMode(EricPathPickerModes.OPEN_FILE_MODE) |
|
76 self.testsuitePicker.setInsertPolicy( |
|
77 QComboBox.InsertPolicy.InsertAtTop) |
|
78 self.testsuitePicker.setSizeAdjustPolicy( |
|
79 QComboBox.SizeAdjustPolicy.AdjustToMinimumContentsLengthWithIcon) |
|
80 |
|
81 self.discoveryPicker.setMode(EricPathPickerModes.DIRECTORY_MODE) |
|
82 self.discoveryPicker.setInsertPolicy( |
|
83 QComboBox.InsertPolicy.InsertAtTop) |
|
84 self.discoveryPicker.setSizeAdjustPolicy( |
|
85 QComboBox.SizeAdjustPolicy.AdjustToMinimumContentsLengthWithIcon) |
|
86 |
|
87 self.testComboBox.lineEdit().setClearButtonEnabled(True) |
|
88 |
|
89 # create some more dialog buttons for orchestration |
|
90 self.__startButton = self.buttonBox.addButton( |
|
91 self.tr("Start"), QDialogButtonBox.ButtonRole.ActionRole) |
|
92 |
|
93 self.__startButton.setToolTip(self.tr( |
|
94 "Start the selected testsuite")) |
|
95 self.__startButton.setWhatsThis(self.tr( |
|
96 """<b>Start Test</b>""" |
|
97 """<p>This button starts the selected testsuite.</p>""")) |
|
98 |
|
99 # TODO: implement "Rerun Failed" |
|
100 ## self.__startFailedButton = self.buttonBox.addButton( |
|
101 ## self.tr("Rerun Failed"), QDialogButtonBox.ButtonRole.ActionRole) |
|
102 ## self.__startFailedButton.setToolTip( |
|
103 ## self.tr("Reruns failed tests of the selected testsuite")) |
|
104 ## self.__startFailedButton.setWhatsThis(self.tr( |
|
105 ## """<b>Rerun Failed</b>""" |
|
106 ## """<p>This button reruns all failed tests of the selected""" |
|
107 ## """ testsuite.</p>""")) |
|
108 ## |
|
109 self.__stopButton = self.buttonBox.addButton( |
|
110 self.tr("Stop"), QDialogButtonBox.ButtonRole.ActionRole) |
|
111 self.__stopButton.setToolTip(self.tr("Stop the running unittest")) |
|
112 self.__stopButton.setWhatsThis(self.tr( |
|
113 """<b>Stop Test</b>""" |
|
114 """<p>This button stops a running unittest.</p>""")) |
|
115 |
|
116 self.__stopButton.setEnabled(False) |
|
117 self.__startButton.setDefault(True) |
|
118 self.__startButton.setEnabled(False) |
|
119 ## self.__startFailedButton.setEnabled(False) |
|
120 |
|
121 self.setWindowFlags( |
|
122 self.windowFlags() | |
|
123 Qt.WindowType.WindowContextHelpButtonHint |
|
124 ) |
|
125 self.setWindowIcon(UI.PixmapCache.getIcon("eric")) |
|
126 self.setWindowTitle(self.tr("Unittest")) |
|
127 |
|
128 from VirtualEnv.VirtualenvManager import VirtualenvManager |
|
129 self.__venvManager = VirtualenvManager(self) |
|
130 self.__venvManager.virtualEnvironmentAdded.connect( |
|
131 self.__populateVenvComboBox) |
|
132 self.__venvManager.virtualEnvironmentRemoved.connect( |
|
133 self.__populateVenvComboBox) |
|
134 self.__venvManager.virtualEnvironmentChanged.connect( |
|
135 self.__populateVenvComboBox) |
|
136 |
|
137 # TODO: implement project mode |
|
138 self.__forProject = False |
|
139 |
|
140 self.__discoverHistory = [] |
|
141 self.__fileHistory = [] |
|
142 self.__testNameHistory = [] |
|
143 self.__recentFramework = "" |
|
144 self.__recentEnvironment = "" |
|
145 |
|
146 self.__failedTests = set() |
|
147 |
|
148 self.__editors = [] |
|
149 self.__testExecutor = None |
|
150 |
|
151 # connect some signals |
|
152 self.frameworkComboBox.currentIndexChanged.connect( |
|
153 self.__updateButtonBoxButtons) |
|
154 self.discoverCheckBox.toggled.connect( |
|
155 self.__updateButtonBoxButtons) |
|
156 self.discoveryPicker.editTextChanged.connect( |
|
157 self.__updateButtonBoxButtons) |
|
158 self.testsuitePicker.editTextChanged.connect( |
|
159 self.__updateButtonBoxButtons) |
|
160 |
|
161 self.__frameworkRegistry = UTFrameworkRegistry() |
|
162 for framework in Frameworks: |
|
163 self.__frameworkRegistry.register(framework) |
|
164 |
|
165 self.__setIdleMode() |
|
166 |
|
167 self.__loadRecent() |
|
168 self.__populateVenvComboBox() |
|
169 |
|
170 if self.__forProject: |
|
171 project = ericApp().getObject("Project") |
|
172 if project.isOpen(): |
|
173 self.__insertDiscovery(project.getProjectPath()) |
|
174 else: |
|
175 self.__insertDiscovery("") |
|
176 else: |
|
177 self.__insertDiscovery("") |
|
178 self.__insertProg(testfile) |
|
179 self.__insertTestName("") |
|
180 |
|
181 self.clearHistoriesButton.clicked.connect(self.clearRecent) |
|
182 |
|
183 self.tabWidget.setCurrentIndex(0) |
|
184 |
|
185 def __populateVenvComboBox(self): |
|
186 """ |
|
187 Private method to (re-)populate the virtual environments selector. |
|
188 """ |
|
189 currentText = self.venvComboBox.currentText() |
|
190 if not currentText: |
|
191 currentText = self.__recentEnvironment |
|
192 |
|
193 self.venvComboBox.clear() |
|
194 self.venvComboBox.addItem("") |
|
195 self.venvComboBox.addItems( |
|
196 sorted(self.__venvManager.getVirtualenvNames())) |
|
197 index = self.venvComboBox.findText(currentText) |
|
198 if index < 0: |
|
199 index = 0 |
|
200 self.venvComboBox.setCurrentIndex(index) |
|
201 |
|
202 def __populateTestFrameworkComboBox(self): |
|
203 """ |
|
204 Private method to (re-)populate the test framework selector. |
|
205 """ |
|
206 currentText = self.frameworkComboBox.currentText() |
|
207 if not currentText: |
|
208 currentText = self.__recentFramework |
|
209 |
|
210 self.frameworkComboBox.clear() |
|
211 |
|
212 if bool(self.venvComboBox.currentText()): |
|
213 interpreter = self.__venvManager.getVirtualenvInterpreter( |
|
214 self.venvComboBox.currentText()) |
|
215 self.frameworkComboBox.addItem("") |
|
216 for index, (name, executor) in enumerate( |
|
217 sorted(self.__frameworkRegistry.getFrameworks().items()), |
|
218 start=1 |
|
219 ): |
|
220 isInstalled = executor.isInstalled(interpreter) |
|
221 entry = ( |
|
222 name |
|
223 if isInstalled else |
|
224 self.tr("{0} (not available)").format(name) |
|
225 ) |
|
226 self.frameworkComboBox.addItem(entry) |
|
227 self.frameworkComboBox.model().item(index).setEnabled( |
|
228 isInstalled) |
|
229 |
|
230 self.frameworkComboBox.setCurrentText(self.__recentFramework) |
|
231 |
|
232 @pyqtSlot(str) |
|
233 def __insertHistory(self, widget, history, item): |
|
234 """ |
|
235 Private slot to insert an item into a history object. |
|
236 |
|
237 @param widget reference to the widget |
|
238 @type QComboBox or EricComboPathPicker |
|
239 @param history array containing the history |
|
240 @type list of str |
|
241 @param item item to be inserted |
|
242 @type str |
|
243 """ |
|
244 current = widget.currentText() |
|
245 |
|
246 # prepend the given directory to the discovery picker |
|
247 if item is None: |
|
248 item = "" |
|
249 if item in history: |
|
250 history.remove(item) |
|
251 history.insert(0, item) |
|
252 widget.clear() |
|
253 widget.addItems(history) |
|
254 |
|
255 if current: |
|
256 widget.setText(current) |
|
257 |
|
258 @pyqtSlot(str) |
|
259 def __insertDiscovery(self, start): |
|
260 """ |
|
261 Private slot to insert the discovery start directory into the |
|
262 discoveryPicker object. |
|
263 |
|
264 @param start start directory name to be inserted |
|
265 @type str |
|
266 """ |
|
267 self.__insertHistory(self.discoveryPicker, self.__discoverHistory, |
|
268 start) |
|
269 |
|
270 @pyqtSlot(str) |
|
271 def __insertProg(self, prog): |
|
272 """ |
|
273 Private slot to insert a test file name into the testsuitePicker |
|
274 object. |
|
275 |
|
276 @param prog test file name to be inserted |
|
277 @type str |
|
278 """ |
|
279 self.__insertHistory(self.testsuitePicker, self.__fileHistory, |
|
280 prog) |
|
281 |
|
282 @pyqtSlot(str) |
|
283 def __insertTestName(self, testName): |
|
284 """ |
|
285 Private slot to insert a test name into the testComboBox object. |
|
286 |
|
287 @param testName name of the test to be inserted |
|
288 @type str |
|
289 """ |
|
290 self.__insertHistory(self.testComboBox, self.__testNameHistory, |
|
291 testName) |
|
292 |
|
293 def __loadRecent(self): |
|
294 """ |
|
295 Private method to load the most recently used lists. |
|
296 """ |
|
297 Preferences.Prefs.rsettings.sync() |
|
298 |
|
299 # 1. recently selected test framework and virtual environment |
|
300 self.__recentEnvironment = Preferences.Prefs.rsettings.value( |
|
301 recentNameUnittestEnvironment, "") |
|
302 self.__recentFramework = Preferences.Prefs.rsettings.value( |
|
303 recentNameUnittestFramework, "") |
|
304 |
|
305 # 2. discovery history |
|
306 self.__discoverHistory = [] |
|
307 rs = Preferences.Prefs.rsettings.value( |
|
308 recentNameUnittestDiscoverHistory) |
|
309 if rs is not None: |
|
310 recent = [f for f in Preferences.toList(rs) if os.path.exists(f)] |
|
311 self.__discoverHistory = recent[ |
|
312 :Preferences.getDebugger("RecentNumber")] |
|
313 |
|
314 # 3. test file history |
|
315 self.__fileHistory = [] |
|
316 rs = Preferences.Prefs.rsettings.value( |
|
317 recentNameUnittestFileHistory) |
|
318 if rs is not None: |
|
319 recent = [f for f in Preferences.toList(rs) if os.path.exists(f)] |
|
320 self.__fileHistory = recent[ |
|
321 :Preferences.getDebugger("RecentNumber")] |
|
322 |
|
323 # 4. test name history |
|
324 self.__testNameHistory = [] |
|
325 rs = Preferences.Prefs.rsettings.value( |
|
326 recentNameUnittestTestnameHistory) |
|
327 if rs is not None: |
|
328 recent = [n for n in Preferences.toList(rs) if n] |
|
329 self.__testNameHistory = recent[ |
|
330 :Preferences.getDebugger("RecentNumber")] |
|
331 |
|
332 def __saveRecent(self): |
|
333 """ |
|
334 Private method to save the most recently used lists. |
|
335 """ |
|
336 Preferences.Prefs.rsettings.setValue( |
|
337 recentNameUnittestEnvironment, self.__recentEnvironment) |
|
338 Preferences.Prefs.rsettings.setValue( |
|
339 recentNameUnittestFramework, self.__recentFramework) |
|
340 Preferences.Prefs.rsettings.setValue( |
|
341 recentNameUnittestDiscoverHistory, self.__discoverHistory) |
|
342 Preferences.Prefs.rsettings.setValue( |
|
343 recentNameUnittestFileHistory, self.__fileHistory) |
|
344 Preferences.Prefs.rsettings.setValue( |
|
345 recentNameUnittestTestnameHistory, self.__testNameHistory) |
|
346 |
|
347 Preferences.Prefs.rsettings.sync() |
|
348 |
|
349 @pyqtSlot() |
|
350 def clearRecent(self): |
|
351 """ |
|
352 Public slot to clear the recently used lists. |
|
353 """ |
|
354 # clear histories |
|
355 self.__discoverHistory = [] |
|
356 self.__fileHistory = [] |
|
357 self.__testNameHistory = [] |
|
358 |
|
359 # clear widgets with histories |
|
360 self.discoveryPicker.clear() |
|
361 self.testsuitePicker.clear() |
|
362 self.testComboBox.clear() |
|
363 |
|
364 # sync histories |
|
365 self.__saveRecent() |
|
366 |
|
367 def __updateButtonBoxButtons(self): |
|
368 """ |
|
369 Private method to update the state of the buttons of the button box. |
|
370 """ |
|
371 failedAvailable = bool(self.__failedTests) |
|
372 |
|
373 # Start button |
|
374 if self.__mode in ( |
|
375 UnittestWidgetModes.IDLE, UnittestWidgetModes.STOPPED |
|
376 ): |
|
377 self.__startButton.setEnabled( |
|
378 bool(self.venvComboBox.currentText()) and |
|
379 bool(self.frameworkComboBox.currentText()) and |
|
380 ( |
|
381 (self.discoverCheckBox.isChecked() and |
|
382 bool(self.discoveryPicker.currentText())) or |
|
383 bool(self.testsuitePicker.currentText()) |
|
384 ) |
|
385 ) |
|
386 self.__startButton.setDefault( |
|
387 self.__mode == UnittestWidgetModes.IDLE or |
|
388 not failedAvailable |
|
389 ) |
|
390 else: |
|
391 self.__startButton.setEnabled(False) |
|
392 self.__startButton.setDefault(False) |
|
393 |
|
394 # Start Failed button |
|
395 # TODO: not implemented yet |
|
396 |
|
397 # Stop button |
|
398 self.__stopButton.setEnabled( |
|
399 self.__mode == UnittestWidgetModes.RUNNING) |
|
400 self.__stopButton.setDefault( |
|
401 self.__mode == UnittestWidgetModes.RUNNING) |
|
402 |
|
403 def __setIdleMode(self): |
|
404 """ |
|
405 Private method to switch the widget to idle mode. |
|
406 """ |
|
407 self.__mode = UnittestWidgetModes.IDLE |
|
408 self.__updateButtonBoxButtons() |
|
409 |
|
410 def __setRunningMode(self): |
|
411 """ |
|
412 Private method to switch the widget to running mode. |
|
413 """ |
|
414 # TODO: not implemented yet |
|
415 pass |
|
416 |
|
417 def __setStoppedMode(self): |
|
418 """ |
|
419 Private method to switch the widget to stopped mode. |
|
420 """ |
|
421 # TODO: not implemented yet |
|
422 pass |
|
423 |
|
424 @pyqtSlot(QAbstractButton) |
|
425 def on_buttonBox_clicked(self, button): |
|
426 """ |
|
427 Private slot called by a button of the button box clicked. |
|
428 |
|
429 @param button button that was clicked |
|
430 @type QAbstractButton |
|
431 """ |
|
432 ## if button == self.discoverButton: |
|
433 ## self.__discover() |
|
434 ## self.__saveRecent() |
|
435 ## elif button == self.__startButton: |
|
436 if button == self.__startButton: |
|
437 self.startTests() |
|
438 self.__saveRecent() |
|
439 elif button == self.__stopButton: |
|
440 self.__stopTests() |
|
441 # elif button == self.__startFailedButton: |
|
442 # self.startTests(failedOnly=True) |
|
443 |
|
444 @pyqtSlot(int) |
|
445 def on_venvComboBox_currentIndexChanged(self, index): |
|
446 """ |
|
447 Private slot handling the selection of a virtual environment. |
|
448 |
|
449 @param index index of the selected environment |
|
450 @type int |
|
451 """ |
|
452 self.__populateTestFrameworkComboBox() |
|
453 self.__updateButtonBoxButtons() |
|
454 |
|
455 self.versionsButton.setEnabled(bool(self.venvComboBox.currentText())) |
|
456 |
|
457 @pyqtSlot() |
|
458 def on_versionsButton_clicked(self): |
|
459 """ |
|
460 Private slot to show the versions of available plugins. |
|
461 """ |
|
462 venvName = self.venvComboBox.currentText() |
|
463 if venvName: |
|
464 headerText = self.tr("<h3>Versions of Frameworks and their" |
|
465 " Plugins</h3>") |
|
466 versionsText = "" |
|
467 interpreter = self.__venvManager.getVirtualenvInterpreter(venvName) |
|
468 for framework in sorted( |
|
469 self.__frameworkRegistry.getFrameworks().keys() |
|
470 ): |
|
471 executor = self.__frameworkRegistry.createExecutor( |
|
472 framework, self) |
|
473 versions = executor.getVersions(interpreter) |
|
474 if versions: |
|
475 txt = "<p><strong>{0} {1}</strong>".format( |
|
476 versions["name"], versions["version"]) |
|
477 |
|
478 if versions["plugins"]: |
|
479 txt += "<table>" |
|
480 for pluginVersion in versions["plugins"]: |
|
481 txt += self.tr( |
|
482 "<tr><td>{0}</td><td>{1}</td></tr>" |
|
483 ).format( |
|
484 pluginVersion["name"], pluginVersion["version"] |
|
485 ) |
|
486 txt += "</table>" |
|
487 txt += "</p>" |
|
488 |
|
489 versionsText += txt |
|
490 |
|
491 if not versionsText: |
|
492 versionsText = self.tr("No version information available.") |
|
493 |
|
494 EricMessageBox.information( |
|
495 self, |
|
496 self.tr("Versions"), |
|
497 headerText + versionsText |
|
498 ) |
|
499 |
|
500 @pyqtSlot() |
|
501 def startTests(self, failedOnly=False): |
|
502 """ |
|
503 Public slot to start the test run. |
|
504 |
|
505 @param failedOnly flag indicating to run only failed tests |
|
506 @type bool |
|
507 """ |
|
508 if self.__mode == UnittestWidgetModes.RUNNING: |
|
509 return |
|
510 |
|
511 self.__recentEnvironment = self.venvComboBox.currentText() |
|
512 self.__recentFramework = self.frameworkComboBox.currentText() |
|
513 |
|
514 discover = self.discoverCheckBox.isChecked() |
|
515 if discover: |
|
516 discoveryStart = self.discoveryPicker.currentText() |
|
517 testFileName = "" |
|
518 testName = "" |
|
519 |
|
520 if discoveryStart: |
|
521 self.__insertDiscovery(discoveryStart) |
|
522 else: |
|
523 discoveryStart = "" |
|
524 testFileName = self.testsuitePicker.currentText() |
|
525 if testFileName: |
|
526 self.__insertProg(testFileName) |
|
527 testName = self.testComboBox.currentText() |
|
528 if testName: |
|
529 self.insertTestName(testName) |
|
530 if testFileName and not testName: |
|
531 testName = "suite" |
|
532 |
|
533 interpreter = self.__venvManager.getVirtualenvInterpreter( |
|
534 self.__recentEnvironment) |
|
535 config = UTTestConfig( |
|
536 interpreter=interpreter, |
|
537 discover=self.discoverCheckBox.isChecked(), |
|
538 discoveryStart=discoveryStart, |
|
539 testFilename=testFileName, |
|
540 testName=testName, |
|
541 failFast=self.failfastCheckBox.isChecked(), |
|
542 collectCoverage=self.coverageCheckBox.isChecked(), |
|
543 eraseCoverage=self.coverageEraseCheckBox.isChecked(), |
|
544 ) |
|
545 |
|
546 self.__resultsModel.clear() |
|
547 self.__testExecutor = self.__frameworkRegistry.createExecutor( |
|
548 self.__recentFramework, self) |
|
549 self.__testExecutor.collected.connect(self.__testCollected) |
|
550 self.__testExecutor.collectError.connect(self.__testsCollectError) |
|
551 self.__testExecutor.startTest.connect(self.__testsStarted) |
|
552 self.__testExecutor.testResult.connect(self.__processTestResult) |
|
553 self.__testExecutor.testFinished.connect(self.__testProcessFinished) |
|
554 self.__testExecutor.stop.connect(self.__testsStopped) |
|
555 self.__testExecutor.start(config, []) |
|
556 |
|
557 # TODO: not yet implemented |
|
558 pass |
|
559 |
|
560 @pyqtSlot(list) |
|
561 def __testCollected(self, testNames): |
|
562 """ |
|
563 Private slot handling the 'collected' signal of the executor. |
|
564 |
|
565 @param testNames list of names of collected tests |
|
566 @type list of str |
|
567 """ |
|
568 # TODO: not implemented yet |
|
569 pass |
|
570 |
|
571 @pyqtSlot(list) |
|
572 def __testsCollectError(self, errors): |
|
573 """ |
|
574 Private slot handling the 'collectError' signal of the executor. |
|
575 |
|
576 @param errors list of tuples containing the test name and a description |
|
577 of the error |
|
578 @type list of tuple of (str, str) |
|
579 """ |
|
580 # TODO: not implemented yet |
|
581 pass |
|
582 |
|
583 @pyqtSlot(list) |
|
584 def __testsStarted(self, testNames): |
|
585 """ |
|
586 Private slot handling the 'startTest' signal of the executor. |
|
587 |
|
588 @param testNames list of names of tests about to be run |
|
589 @type list of str |
|
590 """ |
|
591 # TODO: not implemented yet |
|
592 pass |
|
593 |
|
594 @pyqtSlot(UTTestResult) |
|
595 def __processTestResult(self, result): |
|
596 """ |
|
597 Private slot to handle the receipt of a test result object. |
|
598 |
|
599 @param result test result object |
|
600 @type UTTestResult |
|
601 """ |
|
602 # TODO: not implemented yet |
|
603 pass |
|
604 |
|
605 @pyqtSlot(list, str) |
|
606 def __testProcessFinished(self, results, output): |
|
607 """ |
|
608 Private slot to handle the 'testFinished' signal of the executor. |
|
609 |
|
610 @param results list of test result objects (if not sent via the |
|
611 'testResult' signal |
|
612 @type list of UTTestResult |
|
613 @param output string containing the test process output (if any) |
|
614 @type str |
|
615 """ |
|
616 # TODO: not implemented yet |
|
617 pass |
|
618 |
|
619 @pyqtSlot() |
|
620 def __testsStopped(self): |
|
621 """ |
|
622 Private slot to handle the 'stop' signal of the executor. |
|
623 """ |
|
624 # TODO: not implemented yet |
|
625 pass |
|
626 |
|
627 |
|
628 class UnittestWindow(EricMainWindow): |
|
629 """ |
|
630 Main window class for the standalone dialog. |
|
631 """ |
|
632 def __init__(self, testfile=None, parent=None): |
|
633 """ |
|
634 Constructor |
|
635 |
|
636 @param testfile file name of the test script to open |
|
637 @type str |
|
638 @param parent reference to the parent widget |
|
639 @type QWidget |
|
640 """ |
|
641 super().__init__(parent) |
|
642 self.__cw = UnittestWidget(testfile=testfile, parent=self) |
|
643 self.__cw.installEventFilter(self) |
|
644 size = self.__cw.size() |
|
645 self.setCentralWidget(self.__cw) |
|
646 self.resize(size) |
|
647 |
|
648 self.setStyle(Preferences.getUI("Style"), |
|
649 Preferences.getUI("StyleSheet")) |
|
650 |
|
651 self.__cw.buttonBox.accepted.connect(self.close) |
|
652 self.__cw.buttonBox.rejected.connect(self.close) |
|
653 |
|
654 def eventFilter(self, obj, event): |
|
655 """ |
|
656 Public method to filter events. |
|
657 |
|
658 @param obj reference to the object the event is meant for (QObject) |
|
659 @param event reference to the event object (QEvent) |
|
660 @return flag indicating, whether the event was handled (boolean) |
|
661 """ |
|
662 if event.type() == QEvent.Type.Close: |
|
663 QCoreApplication.exit(0) |
|
664 return True |
|
665 |
|
666 return False |
|
667 |
|
668 |
|
669 def clearSavedHistories(self): |
|
670 """ |
|
671 Function to clear the saved history lists. |
|
672 """ |
|
673 Preferences.Prefs.rsettings.setValue( |
|
674 recentNameUnittestDiscoverHistory, []) |
|
675 Preferences.Prefs.rsettings.setValue( |
|
676 recentNameUnittestFileHistory, []) |
|
677 Preferences.Prefs.rsettings.setValue( |
|
678 recentNameUnittestTestnameHistory, []) |
|
679 |
|
680 Preferences.Prefs.rsettings.sync() |