103 Qt.WindowContextHelpButtonHint)) |
108 Qt.WindowContextHelpButtonHint)) |
104 self.setWindowIcon(UI.PixmapCache.getIcon("eric.png")) |
109 self.setWindowIcon(UI.PixmapCache.getIcon("eric.png")) |
105 self.setWindowTitle(self.tr("Unittest")) |
110 self.setWindowTitle(self.tr("Unittest")) |
106 if dbs: |
111 if dbs: |
107 self.ui = ui |
112 self.ui = ui |
|
113 |
|
114 self.venvComboBox.addItem("") |
|
115 self.venvComboBox.addItems( |
|
116 sorted(e5App().getObject("VirtualEnvManager") |
|
117 .getVirtualenvNames())) |
|
118 self.venvComboBox.setVisible(bool(self.__dbs)) |
|
119 self.venvLabel.setVisible(bool(self.__dbs)) |
|
120 |
108 self.__setProgressColor("green") |
121 self.__setProgressColor("green") |
109 self.progressLed.setDarkFactor(150) |
122 self.progressLed.setDarkFactor(150) |
110 self.progressLed.off() |
123 self.progressLed.off() |
111 |
124 |
112 self.venvComboBox.addItem("") |
125 self.discoverHistory = [] |
113 self.venvComboBox.addItems( |
|
114 sorted(e5App().getObject("VirtualEnvManager") |
|
115 .getVirtualenvNames())) |
|
116 self.venvComboBox.setEnabled(bool(self.__dbs)) |
|
117 |
|
118 self.fileHistory = [] |
126 self.fileHistory = [] |
119 self.testNameHistory = [] |
127 self.testNameHistory = [] |
120 self.running = False |
128 self.running = False |
121 self.savedModulelist = None |
129 self.savedModulelist = None |
122 self.savedSysPath = sys.path |
130 self.savedSysPath = sys.path |
171 |
179 |
172 @param forProject flag indicating to run for the open project |
180 @param forProject flag indicating to run for the open project |
173 @type bool |
181 @type bool |
174 """ |
182 """ |
175 self.__forProject = forProject |
183 self.__forProject = forProject |
|
184 if forProject: |
|
185 project = e5App().getObject("Project") |
|
186 if project.isOpen(): |
|
187 self.insertDiscovery(project.getProjectPath()) |
|
188 else: |
|
189 self.insertDiscovery("") |
|
190 else: |
|
191 self.insertDiscovery("") |
|
192 |
|
193 def insertDiscovery(self, start): |
|
194 """ |
|
195 Public slot to insert the discovery start directory into the |
|
196 discoveryPicker object. |
|
197 |
|
198 @param start start directory name to be inserted |
|
199 @type str |
|
200 """ |
|
201 # prepend the given directory to the discovery picker |
|
202 if start is None: |
|
203 start = "" |
|
204 if start in self.discoverHistory: |
|
205 self.discoverHistory.remove(start) |
|
206 self.discoverHistory.insert(0, start) |
|
207 self.discoveryPicker.clear() |
|
208 self.discoveryPicker.addItems(self.discoverHistory) |
176 |
209 |
177 def insertProg(self, prog): |
210 def insertProg(self, prog): |
178 """ |
211 """ |
179 Public slot to insert the filename prog into the testsuitePicker |
212 Public slot to insert the filename prog into the testsuitePicker |
180 object. |
213 object. |
263 @keyparam failedOnly flag indicating to run only failed tests (boolean) |
317 @keyparam failedOnly flag indicating to run only failed tests (boolean) |
264 """ |
318 """ |
265 if self.running: |
319 if self.running: |
266 return |
320 return |
267 |
321 |
268 prog = self.testsuitePicker.currentText() |
322 discover = self.discoverCheckBox.isChecked() |
269 if not prog: |
323 if discover: |
|
324 discoveryStart = self.discoveryPicker.currentText() |
|
325 prog = "" |
|
326 else: |
|
327 discoveryStart = "" |
|
328 prog = self.testsuitePicker.currentText() |
|
329 |
|
330 if not prog and not discover: |
270 E5MessageBox.critical( |
331 E5MessageBox.critical( |
271 self, |
332 self, |
272 self.tr("Unittest"), |
333 self.tr("Unittest"), |
273 self.tr("You must enter a test suite file.")) |
334 self.tr("You must enter a test suite file or select" |
|
335 " auto-discovery.")) |
274 return |
336 return |
275 |
337 |
276 # prepend the selected file to the testsuite combobox |
338 # prepend the selected file to the testsuite combobox |
277 self.insertProg(prog) |
339 self.insertProg(prog) |
278 self.sbLabel.setText(self.tr("Preparing Testsuite")) |
340 self.sbLabel.setText(self.tr("Preparing Testsuite")) |
279 QApplication.processEvents() |
341 QApplication.processEvents() |
280 |
342 |
281 testFunctionName = self.testComboBox.currentText() |
343 if discover: |
282 if testFunctionName: |
344 testFunctionName = "" |
283 self.insertTestName(testFunctionName) |
345 self.testName = self.tr("Unittest with auto-discovery") |
284 else: |
346 else: |
285 testFunctionName = "suite" |
347 testFunctionName = self.testComboBox.currentText() |
286 |
348 if testFunctionName: |
287 # build the module name from the filename without extension |
349 self.insertTestName(testFunctionName) |
288 self.testName = os.path.splitext(os.path.basename(prog))[0] |
350 else: |
|
351 testFunctionName = "suite" |
|
352 |
|
353 # build the module name from the filename without extension |
|
354 self.testName = os.path.splitext(os.path.basename(prog))[0] |
289 |
355 |
290 if self.__dbs: |
356 if self.__dbs: |
291 # we are cooperating with the eric6 IDE |
357 # we are cooperating with the eric6 IDE |
292 project = e5App().getObject("Project") |
358 project = e5App().getObject("Project") |
293 if self.__forProject and project.isOpen() and \ |
359 if self.__forProject and project.isOpen() and \ |
294 project.isProjectSource(prog): |
360 (discover or project.isProjectSource(prog)): |
295 mainScript = os.path.abspath(project.getMainScript(True)) |
361 mainScript = os.path.abspath(project.getMainScript(True)) |
296 clientType = project.getProjectLanguage() |
362 clientType = project.getProjectLanguage() |
297 sysPath = [os.path.dirname(mainScript)] |
363 if mainScript: |
|
364 workdir = os.path.dirname(mainScript) |
|
365 else: |
|
366 workdir = project.getProjectPath() |
|
367 sysPath = [workdir] |
|
368 if discover and not discoveryStart: |
|
369 discoveryStart = workdir |
298 else: |
370 else: |
299 mainScript = os.path.abspath(prog) |
371 if discover: |
|
372 if not discoveryStart: |
|
373 E5MessageBox.critical( |
|
374 self, |
|
375 self.tr("Unittest"), |
|
376 self.tr("You must enter a start directory for" |
|
377 " auto-discovery.")) |
|
378 return |
|
379 mainScript = os.path.join(discoveryStart, "unittest") |
|
380 workdir = "" |
|
381 # assume Python3 for auto-discovery |
|
382 clientType = "Python3" |
|
383 else: |
|
384 mainScript = os.path.abspath(prog) |
|
385 workdir = os.path.dirname(mainScript) |
|
386 flags = Utilities.extractFlagsFromFile(mainScript) |
|
387 if mainScript.endswith( |
|
388 tuple(Preferences.getPython("PythonExtensions"))) or \ |
|
389 ("FileType" in flags and |
|
390 flags["FileType"] in ["Python", "Python2"]): |
|
391 clientType = "Python2" |
|
392 else: |
|
393 # if it is not Python2 it must be Python3! |
|
394 clientType = "Python3" |
300 sysPath = [] |
395 sysPath = [] |
301 flags = Utilities.extractFlagsFromFile(mainScript) |
396 if not discover and failedOnly and self.__failedTests: |
302 if mainScript.endswith( |
|
303 tuple(Preferences.getPython("PythonExtensions"))) or \ |
|
304 ("FileType" in flags and |
|
305 flags["FileType"] in ["Python", "Python2"]): |
|
306 clientType = "Python2" |
|
307 else: |
|
308 # if it is not Python2 it must be Python3! |
|
309 clientType = "Python3" |
|
310 if failedOnly and self.__failedTests: |
|
311 failed = [t.split(".", 1)[1] for t in self.__failedTests] |
397 failed = [t.split(".", 1)[1] for t in self.__failedTests] |
312 else: |
398 else: |
313 failed = [] |
399 failed = [] |
314 self.__failedTests = [] |
400 self.__failedTests = [] |
315 self.__dbs.remoteUTPrepare( |
401 self.__dbs.remoteUTPrepare( |
316 prog, self.testName, testFunctionName, failed, |
402 prog, self.testName, testFunctionName, failed, |
317 self.coverageCheckBox.isChecked(), mainScript, |
403 self.coverageCheckBox.isChecked(), mainScript, |
318 self.coverageEraseCheckBox.isChecked(), clientType=clientType, |
404 self.coverageEraseCheckBox.isChecked(), clientType=clientType, |
319 forProject=self.__forProject, |
405 forProject=self.__forProject, workdir=workdir, |
320 venvName=self.venvComboBox.currentText(), syspath=sysPath) |
406 venvName=self.venvComboBox.currentText(), syspath=sysPath, |
|
407 discover=discover, discoveryStart=discoveryStart) |
321 else: |
408 else: |
|
409 # TODO: add discovery |
322 # we are running as an application |
410 # we are running as an application |
323 sys.path = [os.path.dirname(os.path.abspath(prog))] + \ |
411 sys.path = [os.path.dirname(os.path.abspath(prog))] + \ |
324 self.savedSysPath |
412 self.savedSysPath |
325 |
413 |
326 # clean up list of imported modules to force a reimport upon |
414 # clean up list of imported modules to force a reimport upon |
332 del(sys.modules[modname]) |
420 del(sys.modules[modname]) |
333 self.savedModulelist = sys.modules.copy() |
421 self.savedModulelist = sys.modules.copy() |
334 |
422 |
335 # now try to generate the testsuite |
423 # now try to generate the testsuite |
336 try: |
424 try: |
337 module = __import__(self.testName) |
425 if discover: |
338 try: |
426 if not discoveryStart: |
339 if failedOnly and self.__failedTests: |
427 E5MessageBox.critical( |
340 test = unittest.defaultTestLoader.loadTestsFromNames( |
428 self, |
341 [t.split(".", 1)[1] for t in self.__failedTests], |
429 self.tr("Unittest"), |
|
430 self.tr("You must enter a start directory for" |
|
431 " auto-discovery.")) |
|
432 return |
|
433 |
|
434 test = unittest.defaultTestLoader.discover(discoveryStart) |
|
435 else: |
|
436 module = __import__(self.testName) |
|
437 try: |
|
438 if failedOnly and self.__failedTests: |
|
439 test = \ |
|
440 unittest.defaultTestLoader.loadTestsFromNames( |
|
441 [t.split(".", 1)[1] |
|
442 for t in self.__failedTests], |
|
443 module) |
|
444 else: |
|
445 test = \ |
|
446 unittest.defaultTestLoader.loadTestsFromName( |
|
447 testFunctionName, module) |
|
448 except AttributeError: |
|
449 test = unittest.defaultTestLoader.loadTestsFromModule( |
342 module) |
450 module) |
343 else: |
|
344 test = unittest.defaultTestLoader.loadTestsFromName( |
|
345 testFunctionName, module) |
|
346 except AttributeError: |
|
347 test = unittest.defaultTestLoader.loadTestsFromModule( |
|
348 module) |
|
349 except Exception: |
451 except Exception: |
350 exc_type, exc_value, exc_tb = sys.exc_info() |
452 exc_type, exc_value, exc_tb = sys.exc_info() |
351 E5MessageBox.critical( |
453 E5MessageBox.critical( |
352 self, |
454 self, |
353 self.tr("Unittest"), |
455 self.tr("Unittest"), |
468 self.progressCounterSkippedCount.setText(str(self.skippedCount)) |
564 self.progressCounterSkippedCount.setText(str(self.skippedCount)) |
469 self.progressCounterExpectedFailureCount.setText( |
565 self.progressCounterExpectedFailureCount.setText( |
470 str(self.expectedFailureCount)) |
566 str(self.expectedFailureCount)) |
471 self.progressCounterUnexpectedSuccessCount.setText( |
567 self.progressCounterUnexpectedSuccessCount.setText( |
472 str(self.unexpectedSuccessCount)) |
568 str(self.unexpectedSuccessCount)) |
|
569 |
473 self.errorsListWidget.clear() |
570 self.errorsListWidget.clear() |
474 self.testsListWidget.clear() |
571 self.testsListWidget.clear() |
|
572 |
475 self.progressProgressBar.setRange(0, self.totalTests) |
573 self.progressProgressBar.setRange(0, self.totalTests) |
476 self.__setProgressColor("green") |
574 self.__setProgressColor("green") |
477 self.progressProgressBar.reset() |
575 self.progressProgressBar.reset() |
|
576 |
478 self.stopButton.setEnabled(True) |
577 self.stopButton.setEnabled(True) |
479 self.startButton.setEnabled(False) |
578 self.startButton.setEnabled(False) |
|
579 self.startFailedButton.setEnabled(False) |
480 self.stopButton.setDefault(True) |
580 self.stopButton.setDefault(True) |
|
581 |
481 self.sbLabel.setText(self.tr("Running")) |
582 self.sbLabel.setText(self.tr("Running")) |
482 self.progressLed.on() |
583 self.progressLed.on() |
483 QApplication.processEvents() |
584 QApplication.processEvents() |
484 |
585 |
485 self.startTime = time.time() |
586 self.startTime = time.time() |
490 """ |
591 """ |
491 self.stopTime = time.time() |
592 self.stopTime = time.time() |
492 self.timeTaken = float(self.stopTime - self.startTime) |
593 self.timeTaken = float(self.stopTime - self.startTime) |
493 self.running = False |
594 self.running = False |
494 |
595 |
|
596 failedAvailable = bool(self.__failedTests) and \ |
|
597 not self.discoverCheckBox.isChecked() |
495 self.startButton.setEnabled(True) |
598 self.startButton.setEnabled(True) |
496 self.startFailedButton.setEnabled(bool(self.__failedTests)) |
599 self.startFailedButton.setEnabled(failedAvailable) |
497 self.stopButton.setEnabled(False) |
600 self.stopButton.setEnabled(False) |
498 if self.__failedTests: |
601 if failedAvailable: |
499 self.startFailedButton.setDefault(True) |
602 self.startFailedButton.setDefault(True) |
500 self.startButton.setDefault(False) |
603 self.startButton.setDefault(False) |
501 else: |
604 else: |
502 self.startFailedButton.setDefault(False) |
605 self.startFailedButton.setDefault(False) |
503 self.startButton.setDefault(True) |
606 self.startButton.setDefault(True) |
504 if self.runCount == 1: |
607 self.sbLabel.setText( |
505 self.sbLabel.setText( |
608 self.tr("Ran %n test(s) in {0:.3f}s", "", self.runCount) |
506 self.tr("Ran {0} test in {1:.3f}s") |
609 .format(self.timeTaken)) |
507 .format(self.runCount, self.timeTaken)) |
|
508 else: |
|
509 self.sbLabel.setText( |
|
510 self.tr("Ran {0} tests in {1:.3f}s") |
|
511 .format(self.runCount, self.timeTaken)) |
|
512 self.progressLed.off() |
610 self.progressLed.off() |
513 |
611 |
514 self.unittestStopped.emit() |
612 self.unittestStopped.emit() |
515 |
613 |
516 def testFailed(self, test, exc, testId): |
614 def testFailed(self, test, exc, testId): |