--- a/PyUnit/UnittestDialog.py Mon Mar 25 20:18:47 2019 +0100 +++ b/PyUnit/UnittestDialog.py Tue Mar 26 19:29:30 2019 +0100 @@ -75,7 +75,6 @@ self.discoveryPicker.setSizeAdjustPolicy( QComboBox.AdjustToMinimumContentsLength) - # TODO: add a "Discover" button enabled upon selection of 'auto-discovery' self.discoverButton = self.buttonBox.addButton( self.tr("Discover"), QDialogButtonBox.ActionRole) self.discoverButton.setToolTip(self.tr( @@ -161,6 +160,7 @@ # now connect the debug server signals if called from the eric6 IDE if self.__dbs: + self.__dbs.utDiscovered.connect(self.__UTDiscovered) self.__dbs.utPrepared.connect(self.__UTPrepared) self.__dbs.utFinished.connect(self.__setStoppedMode) self.__dbs.utStartTest.connect(self.testStarted) @@ -221,6 +221,9 @@ self.insertDiscovery("") else: self.insertDiscovery("") + + self.discoveryList.clear() + self.tabWidget.setCurrentIndex(0) def insertDiscovery(self, start): """ @@ -369,8 +372,38 @@ self.testName = self.tr("Unittest with auto-discovery") if self.__dbs: - # TODO: implement this later - pass + venvName = self.venvComboBox.currentText() + + # we are cooperating with the eric6 IDE + project = e5App().getObject("Project") + if self.__forProject: + mainScript = os.path.abspath(project.getMainScript(True)) + clientType = project.getProjectLanguage() + if mainScript: + workdir = os.path.dirname(mainScript) + else: + workdir = project.getProjectPath() + sysPath = [workdir] + if not discoveryStart: + discoveryStart = workdir + else: + if not discoveryStart: + E5MessageBox.critical( + self, + self.tr("Unittest"), + self.tr("You must enter a start directory for" + " auto-discovery.")) + return + + workdir = "" + clientType = \ + self.__venvManager.getVirtualenvVariant(venvName) + if not clientType: + # assume Python 3 + clientType = "Python3" + self.__dbs.remoteUTDiscover(clientType, self.__forProject, + workdir, venvName, sysPath, + discoveryStart) else: # we are running as an application if not discoveryStart: @@ -399,26 +432,25 @@ try: testLoader = unittest.TestLoader() test = testLoader.discover(discoveryStart) - if test: - if hasattr(testLoader, "errors") and \ - bool(testLoader.errors): - E5MessageBox.critical( - self, - self.tr("Unittest"), - self.tr( - "<p>Unable to discover tests.</p>" - "<p>{0}</p>" - ).format("<br/>".join(testLoader.errors) - .replace("\n", "<br/>")) - ) - self.sbLabel.clear() - else: - testsList = self.__assembleTestCasesList(test) - self.__populateDiscoveryResults(testsList) - self.sbLabel.setText( - self.tr("Discovered %n Test(s)", "", - len(testsList))) - self.tabWidget.setCurrentIndex(0) + if hasattr(testLoader, "errors") and \ + bool(testLoader.errors): + E5MessageBox.critical( + self, + self.tr("Unittest"), + self.tr( + "<p>Unable to discover tests.</p>" + "<p>{0}</p>" + ).format("<br/>".join(testLoader.errors) + .replace("\n", "<br/>")) + ) + self.sbLabel.clear() + else: + testsList = self.__assembleTestCasesList(test) + self.__populateDiscoveryResults(testsList) + self.sbLabel.setText( + self.tr("Discovered %n Test(s)", "", + len(testsList))) + self.tabWidget.setCurrentIndex(0) except Exception: exc_type, exc_value, exc_tb = sys.exc_info() E5MessageBox.critical( @@ -502,6 +534,69 @@ itm.setData(0, Qt.UserRole, modulePath) pitm = itm + def __selectedTestCases(self, parent=None): + """ + Private method to assemble the list of selected test cases and suites. + + @param parent reference to the parent item + @type QTreeWidgetItem + @return list of selected test cases + @rtype list of str + """ + selectedTests = [] + if parent is None: + # top level + 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)) + # ignore children because they are included implicitly + elif itm.childCount(): + # recursively check children + selectedTests.extend(self.__selectedTestCases(itm)) + + else: + # parent item with children + for index in range(parent.childCount()): + itm = parent.child(index) + if itm.checkState(0) == Qt.Checked: + selectedTests.append(itm.data(0, Qt.UserRole)) + # ignore children because they are included implicitly + elif itm.childCount(): + # recursively check children + selectedTests.extend(self.__selectedTestCases(itm)) + + return selectedTests + + def __UTDiscovered(self, testCases, exc_type, exc_value): + """ + Private slot to handle the utPrepared signal. + + If the unittest suite was loaded successfully, we ask the + client to run the test suite. + + @param testCases list of detected test cases + @type str + @param exc_type exception type occured during discovery + @type str + @param exc_value value of exception occured during discovery + @type str + """ + if testCases: + self.__populateDiscoveryResults(testCases) + self.sbLabel.setText( + self.tr("Discovered %n Test(s)", "", + len(testCases))) + self.tabWidget.setCurrentIndex(0) + else: + E5MessageBox.critical( + self, + self.tr("Unittest"), + self.tr("<p>Unable to discover tests.</p>" + "<p>{0}<br>{1}</p>") + .format(exc_type, exc_value.replace("\n", "<br/>")) + ) + @pyqtSlot() def startTests(self, failedOnly=False): """ @@ -551,6 +646,11 @@ else: self.testName = self.tr("<Unnamed Test>") + if failedOnly: + testCases = [] + else: + testCases = self.__selectedTestCases() + if self.__dbs: venvName = self.venvComboBox.currentText() @@ -620,7 +720,8 @@ self.coverageEraseCheckBox.isChecked(), clientType=clientType, forProject=self.__forProject, workdir=workdir, venvName=venvName, syspath=sysPath, - discover=discover, discoveryStart=discoveryStart) + discover=discover, discoveryStart=discoveryStart, + testCases=testCases) else: # we are running as an application if discover and not discoveryStart: @@ -660,7 +761,10 @@ else: failed = [] if discover: - test = testLoader.discover(discoveryStart) + if testCases: + test = testLoader.loadTestsFromNames(testCases) + else: + test = testLoader.discover(discoveryStart) else: if testFileName: module = __import__(self.testName)