390 else: |
395 else: |
391 self.__startButton.setEnabled(False) |
396 self.__startButton.setEnabled(False) |
392 self.__startButton.setDefault(False) |
397 self.__startButton.setDefault(False) |
393 |
398 |
394 # Start Failed button |
399 # Start Failed button |
395 # TODO: not implemented yet |
400 # TODO: not implemented yet (Start Failed button) |
396 |
401 |
397 # Stop button |
402 # Stop button |
398 self.__stopButton.setEnabled( |
403 self.__stopButton.setEnabled( |
399 self.__mode == UnittestWidgetModes.RUNNING) |
404 self.__mode == UnittestWidgetModes.RUNNING) |
400 self.__stopButton.setDefault( |
405 self.__stopButton.setDefault( |
401 self.__mode == UnittestWidgetModes.RUNNING) |
406 self.__mode == UnittestWidgetModes.RUNNING) |
|
407 |
|
408 # Close button |
|
409 self.buttonBox.button( |
|
410 QDialogButtonBox.StandardButton.Close |
|
411 ).setEnabled(self.__mode in ( |
|
412 UnittestWidgetModes.IDLE, UnittestWidgetModes.STOPPED |
|
413 )) |
|
414 |
|
415 def __updateProgress(self): |
|
416 """ |
|
417 Private method update the progress indicators. |
|
418 """ |
|
419 self.progressCounterRunCount.setText( |
|
420 str(self.__runCount)) |
|
421 self.progressCounterRemCount.setText( |
|
422 str(self.__totalCount - self.__runCount)) |
|
423 self.progressProgressBar.setMaximum(self.__totalCount) |
|
424 self.progressProgressBar.setValue(self.__runCount) |
402 |
425 |
403 def __setIdleMode(self): |
426 def __setIdleMode(self): |
404 """ |
427 """ |
405 Private method to switch the widget to idle mode. |
428 Private method to switch the widget to idle mode. |
406 """ |
429 """ |
407 self.__mode = UnittestWidgetModes.IDLE |
430 self.__mode = UnittestWidgetModes.IDLE |
408 self.__updateButtonBoxButtons() |
431 self.__updateButtonBoxButtons() |
|
432 self.tabWidget.setCurrentIndex(0) |
409 |
433 |
410 def __setRunningMode(self): |
434 def __setRunningMode(self): |
411 """ |
435 """ |
412 Private method to switch the widget to running mode. |
436 Private method to switch the widget to running mode. |
413 """ |
437 """ |
414 # TODO: not implemented yet |
438 self.__mode = UnittestWidgetModes.RUNNING |
415 pass |
439 |
|
440 self.__totalCount = 0 |
|
441 self.__runCount = 0 |
|
442 |
|
443 self.__coverageFile = "" |
|
444 # TODO: implement the handling of the 'Show Coverage' button |
|
445 |
|
446 self.sbLabel.setText(self.tr("Running")) |
|
447 self.tabWidget.setCurrentIndex(1) |
|
448 self.__updateButtonBoxButtons() |
|
449 self.__updateProgress() |
|
450 |
|
451 self.__resultsModel.clear() |
416 |
452 |
417 def __setStoppedMode(self): |
453 def __setStoppedMode(self): |
418 """ |
454 """ |
419 Private method to switch the widget to stopped mode. |
455 Private method to switch the widget to stopped mode. |
420 """ |
456 """ |
421 # TODO: not implemented yet |
457 self.__mode = UnittestWidgetModes.STOPPED |
422 pass |
458 |
|
459 self.__updateButtonBoxButtons() |
|
460 |
|
461 self.raise_() |
|
462 self.activateWindow() |
423 |
463 |
424 @pyqtSlot(QAbstractButton) |
464 @pyqtSlot(QAbstractButton) |
425 def on_buttonBox_clicked(self, button): |
465 def on_buttonBox_clicked(self, button): |
426 """ |
466 """ |
427 Private slot called by a button of the button box clicked. |
467 Private slot called by a button of the button box clicked. |
428 |
468 |
429 @param button button that was clicked |
469 @param button button that was clicked |
430 @type QAbstractButton |
470 @type QAbstractButton |
431 """ |
471 """ |
432 ## if button == self.discoverButton: |
|
433 ## self.__discover() |
|
434 ## self.__saveRecent() |
|
435 ## elif button == self.__startButton: |
|
436 if button == self.__startButton: |
472 if button == self.__startButton: |
437 self.startTests() |
473 self.startTests() |
438 self.__saveRecent() |
474 self.__saveRecent() |
439 elif button == self.__stopButton: |
475 elif button == self.__stopButton: |
440 self.__stopTests() |
476 self.__stopTests() |
521 self.__insertDiscovery(discoveryStart) |
557 self.__insertDiscovery(discoveryStart) |
522 else: |
558 else: |
523 discoveryStart = "" |
559 discoveryStart = "" |
524 testFileName = self.testsuitePicker.currentText() |
560 testFileName = self.testsuitePicker.currentText() |
525 if testFileName: |
561 if testFileName: |
526 self.__insertProg(testFileName) |
562 self.__insertTestFile(testFileName) |
527 testName = self.testComboBox.currentText() |
563 testName = self.testComboBox.currentText() |
528 if testName: |
564 if testName: |
529 self.insertTestName(testName) |
565 self.__insertTestName(testName) |
530 if testFileName and not testName: |
566 if testFileName and not testName: |
531 testName = "suite" |
567 testName = "suite" |
|
568 |
|
569 self.sbLabel.setText(self.tr("Preparing Testsuite")) |
|
570 QCoreApplication.processEvents() |
532 |
571 |
533 interpreter = self.__venvManager.getVirtualenvInterpreter( |
572 interpreter = self.__venvManager.getVirtualenvInterpreter( |
534 self.__recentEnvironment) |
573 self.__recentEnvironment) |
535 config = UTTestConfig( |
574 config = UTTestConfig( |
536 interpreter=interpreter, |
575 interpreter=interpreter, |
544 ) |
583 ) |
545 |
584 |
546 self.__resultsModel.clear() |
585 self.__resultsModel.clear() |
547 self.__testExecutor = self.__frameworkRegistry.createExecutor( |
586 self.__testExecutor = self.__frameworkRegistry.createExecutor( |
548 self.__recentFramework, self) |
587 self.__recentFramework, self) |
549 self.__testExecutor.collected.connect(self.__testCollected) |
588 self.__testExecutor.collected.connect(self.__testsCollected) |
550 self.__testExecutor.collectError.connect(self.__testsCollectError) |
589 self.__testExecutor.collectError.connect(self.__testsCollectError) |
551 self.__testExecutor.startTest.connect(self.__testsStarted) |
590 self.__testExecutor.startTest.connect(self.__testStarted) |
552 self.__testExecutor.testResult.connect(self.__processTestResult) |
591 self.__testExecutor.testResult.connect(self.__processTestResult) |
553 self.__testExecutor.testFinished.connect(self.__testProcessFinished) |
592 self.__testExecutor.testFinished.connect(self.__testProcessFinished) |
|
593 self.__testExecutor.testRunFinished.connect(self.__testRunFinished) |
554 self.__testExecutor.stop.connect(self.__testsStopped) |
594 self.__testExecutor.stop.connect(self.__testsStopped) |
|
595 self.__testExecutor.coverageDataSaved.connect(self.__coverageData) |
|
596 |
|
597 self.__setRunningMode() |
555 self.__testExecutor.start(config, []) |
598 self.__testExecutor.start(config, []) |
556 |
599 |
557 # TODO: not yet implemented |
600 @pyqtSlot() |
558 pass |
601 def __stopTests(self): |
|
602 """ |
|
603 Private slot to stop the current test run. |
|
604 """ |
|
605 self.__testExecutor.stopIfRunning() |
559 |
606 |
560 @pyqtSlot(list) |
607 @pyqtSlot(list) |
561 def __testCollected(self, testNames): |
608 def __testsCollected(self, testNames): |
562 """ |
609 """ |
563 Private slot handling the 'collected' signal of the executor. |
610 Private slot handling the 'collected' signal of the executor. |
564 |
611 |
565 @param testNames list of names of collected tests |
612 @param testNames list of tuples containing the test id and test name |
566 @type list of str |
613 of collected tests |
567 """ |
614 @type list of tuple of (str, str) |
568 # TODO: not implemented yet |
615 """ |
569 pass |
616 testResults = [ |
|
617 UTTestResult( |
|
618 category=ResultCategory.PENDING, |
|
619 status=self.tr("pending"), |
|
620 name=name, |
|
621 id=id, |
|
622 message=desc, |
|
623 ) for id, name, desc in testNames |
|
624 ] |
|
625 self.__resultsModel.setTestResults(testResults) |
|
626 |
|
627 self.__totalCount = len(testResults) |
|
628 self.__updateProgress() |
570 |
629 |
571 @pyqtSlot(list) |
630 @pyqtSlot(list) |
572 def __testsCollectError(self, errors): |
631 def __testsCollectError(self, errors): |
573 """ |
632 """ |
574 Private slot handling the 'collectError' signal of the executor. |
633 Private slot handling the 'collectError' signal of the executor. |
575 |
634 |
576 @param errors list of tuples containing the test name and a description |
635 @param errors list of tuples containing the test name and a description |
577 of the error |
636 of the error |
578 @type list of tuple of (str, str) |
637 @type list of tuple of (str, str) |
579 """ |
638 """ |
580 # TODO: not implemented yet |
639 testResults = [] |
581 pass |
640 |
582 |
641 for testFile, error in errors: |
583 @pyqtSlot(list) |
642 if testFile: |
584 def __testsStarted(self, testNames): |
643 testResults.append(UTTestResult( |
|
644 category=ResultCategory.FAIL, |
|
645 status=self.tr("Failure"), |
|
646 name=testFile, |
|
647 id=testFile, |
|
648 message=self.tr("Collection Error"), |
|
649 extra=error.splitlines() |
|
650 )) |
|
651 else: |
|
652 EricMessageBox.critical( |
|
653 self, |
|
654 self.tr("Collection Error"), |
|
655 self.tr( |
|
656 "<p>There was an error while collecting unit tests." |
|
657 "</p><p>{0}</p>" |
|
658 ).format("<br/>".join(error.splitlines())) |
|
659 ) |
|
660 |
|
661 if testResults: |
|
662 self.__resultsModel.addTestResults(testResults) |
|
663 |
|
664 @pyqtSlot(tuple) |
|
665 def __testStarted(self, test): |
585 """ |
666 """ |
586 Private slot handling the 'startTest' signal of the executor. |
667 Private slot handling the 'startTest' signal of the executor. |
587 |
668 |
588 @param testNames list of names of tests about to be run |
669 @param test tuple containing the id, name and short description of the |
589 @type list of str |
670 tests about to be run |
590 """ |
671 @type tuple of (str, str, str) |
591 # TODO: not implemented yet |
672 """ |
592 pass |
673 self.__resultsModel.updateTestResults([ |
|
674 UTTestResult( |
|
675 category=ResultCategory.RUNNING, |
|
676 status=self.tr("running"), |
|
677 id=test[0], |
|
678 name=test[1], |
|
679 message="" if test[2] is None else test[2], |
|
680 ) |
|
681 ]) |
593 |
682 |
594 @pyqtSlot(UTTestResult) |
683 @pyqtSlot(UTTestResult) |
595 def __processTestResult(self, result): |
684 def __processTestResult(self, result): |
596 """ |
685 """ |
597 Private slot to handle the receipt of a test result object. |
686 Private slot to handle the receipt of a test result object. |
598 |
687 |
599 @param result test result object |
688 @param result test result object |
600 @type UTTestResult |
689 @type UTTestResult |
601 """ |
690 """ |
602 # TODO: not implemented yet |
691 self.__runCount += 1 |
603 pass |
692 self.__updateProgress() |
|
693 |
|
694 self.__resultsModel.updateTestResults([result]) |
604 |
695 |
605 @pyqtSlot(list, str) |
696 @pyqtSlot(list, str) |
606 def __testProcessFinished(self, results, output): |
697 def __testProcessFinished(self, results, output): |
607 """ |
698 """ |
608 Private slot to handle the 'testFinished' signal of the executor. |
699 Private slot to handle the 'testFinished' signal of the executor. |
611 'testResult' signal |
702 'testResult' signal |
612 @type list of UTTestResult |
703 @type list of UTTestResult |
613 @param output string containing the test process output (if any) |
704 @param output string containing the test process output (if any) |
614 @type str |
705 @type str |
615 """ |
706 """ |
616 # TODO: not implemented yet |
707 self.__setStoppedMode() |
617 pass |
708 self.__testExecutor = None |
|
709 |
|
710 @pyqtSlot(int, float) |
|
711 def __testRunFinished(self, noTests, duration): |
|
712 """ |
|
713 Private slot to handle the 'testRunFinished' signal of the executor. |
|
714 |
|
715 @param noTests number of tests run by the executor |
|
716 @type int |
|
717 @param duration time needed in seconds to run the tests |
|
718 @type float |
|
719 """ |
|
720 self.sbLabel.setText( |
|
721 self.tr("Ran %n test(s) in {0}s", "", noTests).format( |
|
722 locale.format_string("%.3f", duration, grouping=True) |
|
723 ) |
|
724 ) |
|
725 |
|
726 self.__setStoppedMode() |
618 |
727 |
619 @pyqtSlot() |
728 @pyqtSlot() |
620 def __testsStopped(self): |
729 def __testsStopped(self): |
621 """ |
730 """ |
622 Private slot to handle the 'stop' signal of the executor. |
731 Private slot to handle the 'stop' signal of the executor. |
623 """ |
732 """ |
624 # TODO: not implemented yet |
733 self.sbLabel.setText(self.tr("Ran %n test(s)", "", self.__runCount)) |
625 pass |
734 |
|
735 self.__setStoppedMode() |
|
736 |
|
737 @pyqtSlot(str) |
|
738 def __coverageData(self, coverageFile): |
|
739 """ |
|
740 Private slot to handle the 'coverageData' signal of the executor. |
|
741 |
|
742 @param coverageFile file containing the coverage data |
|
743 @type str |
|
744 """ |
|
745 self.__coverageFile = coverageFile |
|
746 |
|
747 # TODO: implement the handling of the 'Show Coverage' button |
626 |
748 |
627 |
749 |
628 class UnittestWindow(EricMainWindow): |
750 class UnittestWindow(EricMainWindow): |
629 """ |
751 """ |
630 Main window class for the standalone dialog. |
752 Main window class for the standalone dialog. |