Test: Final application of pre-commit
This commit is contained in:
committed by
Chris Hennes
parent
217674de04
commit
efd11e590d
@@ -113,7 +113,7 @@ Click 'start', and the test thus produced will be run.
|
||||
|
||||
Double click on an error in the tree view to see more information about it, including the stack trace.</source>
|
||||
<translation>Introduïu el nom d'un objecte cridable que quan es cridi retorni un TestCase.
|
||||
Feu clic a 'Comença' i s'executarà el test anteriorment produït.
|
||||
Feu clic a 'Comença' i s'executarà el test anteriorment produït.
|
||||
|
||||
Feu doble clic a un error a la vista d'arbre per veure'n més informació, incloent-hi la traça de pila.</translation>
|
||||
</message>
|
||||
|
||||
@@ -127,7 +127,7 @@ Haga doble clic en un error en la vista de árbol para ver más información al
|
||||
<source>Copyright (c) Werner Mayer
|
||||
|
||||
FreeCAD UnitTest is part of FreeCAD and supports writing Unit Tests for ones own modules.</source>
|
||||
<translation>Copyright (c) Werner Mayer
|
||||
<translation>Copyright (c) Werner Mayer
|
||||
|
||||
Unidad de Prueba FreeCAD es parte de FreeCAD y soporta escribir pruebas unitarias para los propios módulos.</translation>
|
||||
</message>
|
||||
|
||||
@@ -127,7 +127,7 @@ Haga doble clic en un error en la vista de árbol para ver más información sob
|
||||
<source>Copyright (c) Werner Mayer
|
||||
|
||||
FreeCAD UnitTest is part of FreeCAD and supports writing Unit Tests for ones own modules.</source>
|
||||
<translation>Copyright (c) Werner Mayer
|
||||
<translation>Copyright (c) Werner Mayer
|
||||
|
||||
FreeCAD UnitTest es parte de FreeCAD y soporta escribir pruebas unitarias para los propios módulos.</translation>
|
||||
</message>
|
||||
|
||||
@@ -113,7 +113,7 @@ Click 'start', and the test thus produced will be run.
|
||||
|
||||
Double click on an error in the tree view to see more information about it, including the stack trace.</source>
|
||||
<translation>Írja be a nevét a hívható objektumnak, amely hívásakor, visszatér egy Tesztre.
|
||||
Nyomjon 'Indítás'-t, és az így készült vizsgálat futni fog.
|
||||
Nyomjon 'Indítás'-t, és az így készült vizsgálat futni fog.
|
||||
|
||||
Dupla kattintással, a fa nézeten további információkat kap, beleértve a verem-nyomkövetést.</translation>
|
||||
</message>
|
||||
@@ -127,7 +127,7 @@ Dupla kattintással, a fa nézeten további információkat kap, beleértve a ve
|
||||
<source>Copyright (c) Werner Mayer
|
||||
|
||||
FreeCAD UnitTest is part of FreeCAD and supports writing Unit Tests for ones own modules.</source>
|
||||
<translation>Copyright (c) Werner Mayer
|
||||
<translation>Copyright (c) Werner Mayer
|
||||
|
||||
FreeCAD UnitTest része a FreeCAD programnak és támogatja a saját modulokra a Unit tesztek írását.</translation>
|
||||
</message>
|
||||
|
||||
@@ -126,7 +126,7 @@ Fare doppio clic su un errore nell'albero per visualizzare maggiori informazioni
|
||||
<source>Copyright (c) Werner Mayer
|
||||
|
||||
FreeCAD UnitTest is part of FreeCAD and supports writing Unit Tests for ones own modules.</source>
|
||||
<translation>Copyright (c) Werner Mayer
|
||||
<translation>Copyright (c) Werner Mayer
|
||||
|
||||
FreeCAD UnitTest fa parte di FreeCAD e supporta la scrittura di Unit test per i propri moduli.</translation>
|
||||
</message>
|
||||
|
||||
@@ -113,7 +113,7 @@ Click 'start', and the test thus produced will be run.
|
||||
|
||||
Double click on an error in the tree view to see more information about it, including the stack trace.</source>
|
||||
<translation>Nhập tên của một đối tượng có thể gọi được và khi đối tượng đó được gọi, nó trở lại thành một Trường hợp kiểm tra.
|
||||
Nhấp chuột 'bắt đầu', sau đó bài kiểm tra được tạo sẽ hoạt động.
|
||||
Nhấp chuột 'bắt đầu', sau đó bài kiểm tra được tạo sẽ hoạt động.
|
||||
|
||||
Nhấp đúp vào một lỗi trong chế độ xem hình cây để xem thêm thông tin về nó, bao gồm cả ngăn xếp.</translation>
|
||||
</message>
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
#***************************************************************************
|
||||
#* Copyright (c) 2006 Werner Mayer <werner.wm.mayer@gmx.de> *
|
||||
#* *
|
||||
#* This file is part of the FreeCAD CAx development system. *
|
||||
#* *
|
||||
#* This program is free software; you can redistribute it and/or modify *
|
||||
#* it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
#* as published by the Free Software Foundation; either version 2 of *
|
||||
#* the License, or (at your option) any later version. *
|
||||
#* for detail see the LICENCE text file. *
|
||||
#* *
|
||||
#* FreeCAD is distributed in the hope that it will be useful, *
|
||||
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
#* GNU Library General Public License for more details. *
|
||||
#* *
|
||||
#* You should have received a copy of the GNU Library General Public *
|
||||
#* License along with FreeCAD; if not, write to the Free Software *
|
||||
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
#* USA *
|
||||
#***************************************************************************/
|
||||
# ***************************************************************************
|
||||
# * Copyright (c) 2006 Werner Mayer <werner.wm.mayer@gmx.de> *
|
||||
# * *
|
||||
# * This file is part of the FreeCAD CAx development system. *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * FreeCAD is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with FreeCAD; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# ***************************************************************************/
|
||||
|
||||
# Qt Unit test module
|
||||
|
||||
@@ -29,7 +29,7 @@ import traceback
|
||||
|
||||
# Cannot import this file in case Python is not prepared for Tk.
|
||||
# Copy the needed classes instead.
|
||||
#import unittestgui
|
||||
# import unittestgui
|
||||
|
||||
import unittest
|
||||
import sys
|
||||
@@ -45,12 +45,14 @@ import string
|
||||
# For more details see also http://pyunit.sourceforge.net.
|
||||
##############################################################################
|
||||
|
||||
|
||||
class BaseGUITestRunner:
|
||||
"""Subclass this class to create a GUI TestRunner that uses a specific
|
||||
windowing toolkit. The class takes care of running tests in the correct
|
||||
manner, and making callbacks to the derived class to obtain information
|
||||
or signal that events have occurred.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.currentResult = None
|
||||
self.running = 0
|
||||
@@ -67,7 +69,8 @@ class BaseGUITestRunner:
|
||||
|
||||
def runClicked(self):
|
||||
"To be called in response to user choosing to run a test"
|
||||
if self.running: return
|
||||
if self.running:
|
||||
return
|
||||
testName = self.getSelectedTestName()
|
||||
if not testName:
|
||||
self.errorDialog("Test name entry", "You must enter a test name")
|
||||
@@ -79,11 +82,12 @@ class BaseGUITestRunner:
|
||||
test = unittest.defaultTestLoader.loadTestsFromName(testName)
|
||||
except Exception:
|
||||
exc_type, exc_value, exc_tb = sys.exc_info()
|
||||
#apply(traceback.print_exception,sys.exc_info())
|
||||
# apply(traceback.print_exception,sys.exc_info())
|
||||
traceback.print_exception(*sys.exc_info())
|
||||
self.errorDialog("Unable to run test '%s'" % testName,
|
||||
"Error loading specified test: %s, %s" % \
|
||||
(exc_type, exc_value))
|
||||
self.errorDialog(
|
||||
"Unable to run test '%s'" % testName,
|
||||
"Error loading specified test: %s, %s" % (exc_type, exc_value),
|
||||
)
|
||||
return
|
||||
self.currentResult = GUITestResult(self)
|
||||
self.totalTests = test.countTestCases()
|
||||
@@ -98,15 +102,17 @@ class BaseGUITestRunner:
|
||||
|
||||
expectedFails = unexpectedSuccesses = skipped = 0
|
||||
try:
|
||||
results = map(len, (result.expectedFailures,
|
||||
result.unexpectedSuccesses,
|
||||
result.skipped))
|
||||
results = map(
|
||||
len, (result.expectedFailures, result.unexpectedSuccesses, result.skipped)
|
||||
)
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
expectedFails, unexpectedSuccesses, skipped = results
|
||||
|
||||
self.stream.write("\n{}\nRan {} tests in {:.3}s\n\n".format("-" * 70, result.testsRun, timeTaken))
|
||||
self.stream.write(
|
||||
"\n{}\nRan {} tests in {:.3}s\n\n".format("-" * 70, result.testsRun, timeTaken)
|
||||
)
|
||||
infos = []
|
||||
if not result.wasSuccessful():
|
||||
failed, errored = len(result.failures), len(result.errors)
|
||||
@@ -125,7 +131,6 @@ class BaseGUITestRunner:
|
||||
else:
|
||||
self.stream.write("OK\n")
|
||||
|
||||
|
||||
def stopClicked(self):
|
||||
"To be called in response to user stopping the running of a test"
|
||||
if self.currentResult:
|
||||
@@ -155,7 +160,7 @@ class BaseGUITestRunner:
|
||||
|
||||
def notifyTestFinished(self, test):
|
||||
"""Override to indicate that a test has finished (it may already have
|
||||
failed or errored)"""
|
||||
failed or errored)"""
|
||||
pass
|
||||
|
||||
|
||||
@@ -163,6 +168,7 @@ class GUITestResult(unittest.TestResult):
|
||||
"""A TestResult that makes callbacks to its associated GUI TestRunner.
|
||||
Used by BaseGUITestRunner. Need not be created directly.
|
||||
"""
|
||||
|
||||
def __init__(self, callback):
|
||||
unittest.TestResult.__init__(self)
|
||||
self.callback = callback
|
||||
@@ -188,6 +194,7 @@ class RollbackImporter:
|
||||
"""This tricky little class is used to make sure that modules under test
|
||||
will be reloaded the next time they are imported.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.previousModules = sys.modules.copy()
|
||||
|
||||
@@ -195,18 +202,17 @@ class RollbackImporter:
|
||||
for modname in sys.modules.keys():
|
||||
if modname not in self.previousModules:
|
||||
# Force reload when modname next imported
|
||||
del(sys.modules[modname])
|
||||
del sys.modules[modname]
|
||||
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------------
|
||||
# Subclass of BaseGUITestRunner using Qt dialog
|
||||
#---------------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class QtTestRunner(BaseGUITestRunner):
|
||||
"""An implementation of BaseGUITestRunner using Qt.
|
||||
"""
|
||||
"""An implementation of BaseGUITestRunner using Qt."""
|
||||
|
||||
def initGUI(self, root, initialTestName):
|
||||
"""Set up the GUI inside the given root window. The test name entry
|
||||
field will be pre-filled with the given initialTestName.
|
||||
@@ -214,7 +220,8 @@ class QtTestRunner(BaseGUITestRunner):
|
||||
self.root = root
|
||||
# Set up values that will be tied to widgets
|
||||
import QtUnitGui
|
||||
self.gui=QtUnitGui.UnitTest()
|
||||
|
||||
self.gui = QtUnitGui.UnitTest()
|
||||
self.gui.setStatusText("Idle")
|
||||
self.runCountVar = 0
|
||||
self.failCountVar = 0
|
||||
@@ -229,13 +236,13 @@ class QtTestRunner(BaseGUITestRunner):
|
||||
return self.gui.errorDialog(title, message)
|
||||
|
||||
def notifyRunning(self):
|
||||
self.runCountVar=0
|
||||
self.runCountVar = 0
|
||||
self.gui.setRunCount(0)
|
||||
self.failCountVar=0
|
||||
self.failCountVar = 0
|
||||
self.gui.setFailCount(0)
|
||||
self.errorCountVar=0
|
||||
self.errorCountVar = 0
|
||||
self.gui.setErrorCount(0)
|
||||
self.remainingCountVar=self.totalTests
|
||||
self.remainingCountVar = self.totalTests
|
||||
self.gui.setRemainCount(self.totalTests)
|
||||
self.errorInfo = []
|
||||
self.gui.clearErrorList()
|
||||
@@ -250,32 +257,32 @@ class QtTestRunner(BaseGUITestRunner):
|
||||
self.gui.updateGUI()
|
||||
|
||||
def notifyTestFailed(self, test, err):
|
||||
self.failCountVar=self.failCountVar+1
|
||||
self.failCountVar = self.failCountVar + 1
|
||||
self.gui.setFailCount(self.failCountVar)
|
||||
#tracebackLines = apply(traceback.format_exception, err + (10,))
|
||||
# tracebackLines = apply(traceback.format_exception, err + (10,))
|
||||
tracebackLines = traceback.format_exception(*err + (10,))
|
||||
#tracebackText = string.join(tracebackLines,'')
|
||||
tracebackText = ''.join(tracebackLines)
|
||||
self.gui.insertError("Failure: %s" % test,tracebackText)
|
||||
self.errorInfo.append((test,err))
|
||||
# tracebackText = string.join(tracebackLines,'')
|
||||
tracebackText = "".join(tracebackLines)
|
||||
self.gui.insertError("Failure: %s" % test, tracebackText)
|
||||
self.errorInfo.append((test, err))
|
||||
self.stream.write("FAILED: {}\n{}\n".format(test, tracebackText))
|
||||
|
||||
def notifyTestErrored(self, test, err):
|
||||
self.errorCountVar=self.errorCountVar+1
|
||||
self.errorCountVar = self.errorCountVar + 1
|
||||
self.gui.setErrorCount(self.errorCountVar)
|
||||
#tracebackLines = apply(traceback.format_exception, err + (10,))
|
||||
# tracebackLines = apply(traceback.format_exception, err + (10,))
|
||||
tracebackLines = traceback.format_exception(*err + (10,))
|
||||
#tracebackText = string.join(tracebackLines,'')
|
||||
tracebackText = ''.join(tracebackLines)
|
||||
self.gui.insertError("Error: %s" % test,tracebackText)
|
||||
self.errorInfo.append((test,err))
|
||||
# tracebackText = string.join(tracebackLines,'')
|
||||
tracebackText = "".join(tracebackLines)
|
||||
self.gui.insertError("Error: %s" % test, tracebackText)
|
||||
self.errorInfo.append((test, err))
|
||||
self.stream.write("{}\nERROR: {}\n{}\n{}\n".format("=" * 70, test, "-" * 70, tracebackText))
|
||||
|
||||
def notifyTestFinished(self, test):
|
||||
self.remainingCountVar=self.remainingCountVar-1
|
||||
self.remainingCountVar = self.remainingCountVar - 1
|
||||
self.gui.setRemainCount(self.remainingCountVar)
|
||||
self.runCountVar=self.runCountVar+1
|
||||
self.runCountVar = self.runCountVar + 1
|
||||
self.gui.setRunCount(self.runCountVar)
|
||||
fractionDone = float(self.runCountVar)/float(self.totalTests)
|
||||
fractionDone = float(self.runCountVar) / float(self.totalTests)
|
||||
fillColor = len(self.errorInfo) and "red" or "green"
|
||||
self.gui.setProgressFraction(fractionDone, fillColor)
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
<name>Bad root node</name>
|
||||
<description>The root node is not called "package".</description>
|
||||
<version>1.0.0</version>
|
||||
</notpackage>
|
||||
</notpackage>
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
<name>Bad format</name>
|
||||
<description>There is no such thing as format version 2 (yet).</description>
|
||||
<version>1.0.0</version>
|
||||
</package>
|
||||
</package>
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
<package format="1" xmlns="https://wiki.freecad.org/Package_Metadata">
|
||||
<name>Bad XML</notname>
|
||||
<description>The name tag is not closed properly.</description>
|
||||
</package>
|
||||
</package>
|
||||
|
||||
@@ -18,4 +18,4 @@
|
||||
<icon>Resources/icons/PackageIcon.svg</icon>
|
||||
<tag>Tag0</tag>
|
||||
<tag>Tag1</tag>
|
||||
</package>
|
||||
</package>
|
||||
|
||||
@@ -60,5 +60,5 @@
|
||||
<name>Doesn't Really Matter</name>
|
||||
</other_content_item>
|
||||
</content>
|
||||
|
||||
</package>
|
||||
|
||||
</package>
|
||||
|
||||
@@ -5,4 +5,3 @@
|
||||
See \ref src/Mod/Draft/draft.dox for example on how to populate a .dox file.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
@@ -40,12 +40,14 @@ import string
|
||||
# GUI framework classes
|
||||
##############################################################################
|
||||
|
||||
|
||||
class BaseGUITestRunner:
|
||||
"""Subclass this class to create a GUI TestRunner that uses a specific
|
||||
windowing toolkit. The class takes care of running tests in the correct
|
||||
manner, and making callbacks to the derived class to obtain information
|
||||
or signal that events have occurred.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.currentResult = None
|
||||
self.running = 0
|
||||
@@ -62,7 +64,8 @@ class BaseGUITestRunner:
|
||||
|
||||
def runClicked(self):
|
||||
"To be called in response to user choosing to run a test"
|
||||
if self.running: return
|
||||
if self.running:
|
||||
return
|
||||
testName = self.getSelectedTestName()
|
||||
if not testName:
|
||||
self.errorDialog("Test name entry", "You must enter a test name")
|
||||
@@ -75,9 +78,10 @@ class BaseGUITestRunner:
|
||||
except Exception:
|
||||
exc_type, exc_value, exc_tb = sys.exc_info()
|
||||
traceback.print_exception(*sys.exc_info())
|
||||
self.errorDialog("Unable to run test '%s'" % testName,
|
||||
"Error loading specified test: %s, %s" % \
|
||||
(exc_type, exc_value))
|
||||
self.errorDialog(
|
||||
"Unable to run test '%s'" % testName,
|
||||
"Error loading specified test: %s, %s" % (exc_type, exc_value),
|
||||
)
|
||||
return
|
||||
self.currentResult = GUITestResult(self)
|
||||
self.totalTests = test.countTestCases()
|
||||
@@ -116,7 +120,7 @@ class BaseGUITestRunner:
|
||||
|
||||
def notifyTestFinished(self, test):
|
||||
"""Override to indicate that a test has finished (it may already have
|
||||
failed or errored)"""
|
||||
failed or errored)"""
|
||||
pass
|
||||
|
||||
|
||||
@@ -124,6 +128,7 @@ class GUITestResult(unittest.TestResult):
|
||||
"""A TestResult that makes callbacks to its associated GUI TestRunner.
|
||||
Used by BaseGUITestRunner. Need not be created directly.
|
||||
"""
|
||||
|
||||
def __init__(self, callback):
|
||||
unittest.TestResult.__init__(self)
|
||||
self.callback = callback
|
||||
@@ -149,21 +154,22 @@ class RollbackImporter:
|
||||
"""This tricky little class is used to make sure that modules under test
|
||||
will be reloaded the next time they are imported.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.previousModules = sys.modules.copy()
|
||||
|
||||
|
||||
def rollbackImports(self):
|
||||
for modname in sys.modules.keys():
|
||||
if modname not in self.previousModules:
|
||||
# Force reload when modname next imported
|
||||
del(sys.modules[modname])
|
||||
del sys.modules[modname]
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Tkinter GUI
|
||||
##############################################################################
|
||||
|
||||
_ABOUT_TEXT="""\
|
||||
_ABOUT_TEXT = """\
|
||||
PyUnit unit testing framework.
|
||||
|
||||
For more information, visit
|
||||
@@ -172,7 +178,7 @@ http://pyunit.sourceforge.net/
|
||||
Copyright (c) 2000 Steve Purcell
|
||||
<stephen_purcell@yahoo.com>
|
||||
"""
|
||||
_HELP_TEXT="""\
|
||||
_HELP_TEXT = """\
|
||||
Enter the name of a callable object which, when called, will return a \
|
||||
TestCase or TestSuite. Click 'start', and the test thus produced will be run.
|
||||
|
||||
@@ -184,9 +190,10 @@ http://pyunit.sourceforge.net/
|
||||
or see the bundled documentation
|
||||
"""
|
||||
|
||||
|
||||
class TkTestRunner(BaseGUITestRunner):
|
||||
"""An implementation of BaseGUITestRunner using Tkinter.
|
||||
"""
|
||||
"""An implementation of BaseGUITestRunner using Tkinter."""
|
||||
|
||||
def initGUI(self, root, initialTestName):
|
||||
"""Set up the GUI inside the given root window. The test name entry
|
||||
field will be pre-filled with the given initialTestName.
|
||||
@@ -207,7 +214,7 @@ class TkTestRunner(BaseGUITestRunner):
|
||||
|
||||
def createWidgets(self):
|
||||
"""Creates and packs the various widgets.
|
||||
|
||||
|
||||
Why is it that GUI code always ends up looking a mess, despite all the
|
||||
best intentions to keep it tidy? Answers on a postcard, please.
|
||||
"""
|
||||
@@ -225,61 +232,58 @@ class TkTestRunner(BaseGUITestRunner):
|
||||
e = tk.Entry(suiteNameFrame, textvariable=self.suiteNameVar, width=25)
|
||||
e.pack(side=tk.LEFT, fill=tk.X, expand=1)
|
||||
e.focus_set()
|
||||
e.bind('<Key-Return>', lambda e, self=self: self.runClicked())
|
||||
e.bind("<Key-Return>", lambda e, self=self: self.runClicked())
|
||||
|
||||
# Progress bar
|
||||
progressFrame = tk.Frame(leftFrame, relief=tk.GROOVE, borderwidth=2)
|
||||
progressFrame.pack(fill=tk.X, expand=0, anchor=tk.NW)
|
||||
tk.Label(progressFrame, text="Progress:").pack(anchor=tk.W)
|
||||
self.progressBar = ProgressBar(progressFrame, relief=tk.SUNKEN,
|
||||
borderwidth=2)
|
||||
self.progressBar = ProgressBar(progressFrame, relief=tk.SUNKEN, borderwidth=2)
|
||||
self.progressBar.pack(fill=tk.X, expand=1)
|
||||
|
||||
# Area with buttons to start/stop tests and quit
|
||||
buttonFrame = tk.Frame(self.top, borderwidth=3)
|
||||
buttonFrame.pack(side=tk.LEFT, anchor=tk.NW, fill=tk.Y)
|
||||
self.stopGoButton = tk.Button(buttonFrame, text="Start",
|
||||
command=self.runClicked)
|
||||
self.stopGoButton = tk.Button(buttonFrame, text="Start", command=self.runClicked)
|
||||
self.stopGoButton.pack(fill=tk.X)
|
||||
tk.Button(buttonFrame, text="Close",
|
||||
command=self.top.quit).pack(side=tk.BOTTOM, fill=tk.X)
|
||||
tk.Button(buttonFrame, text="About",
|
||||
command=self.showAboutDialog).pack(side=tk.BOTTOM, fill=tk.X)
|
||||
tk.Button(buttonFrame, text="Help",
|
||||
command=self.showHelpDialog).pack(side=tk.BOTTOM, fill=tk.X)
|
||||
tk.Button(buttonFrame, text="Close", command=self.top.quit).pack(side=tk.BOTTOM, fill=tk.X)
|
||||
tk.Button(buttonFrame, text="About", command=self.showAboutDialog).pack(
|
||||
side=tk.BOTTOM, fill=tk.X
|
||||
)
|
||||
tk.Button(buttonFrame, text="Help", command=self.showHelpDialog).pack(
|
||||
side=tk.BOTTOM, fill=tk.X
|
||||
)
|
||||
|
||||
# Area with labels reporting results
|
||||
for label, var in (('Run:', self.runCountVar),
|
||||
('Failures:', self.failCountVar),
|
||||
('Errors:', self.errorCountVar),
|
||||
('Remaining:', self.remainingCountVar)):
|
||||
for label, var in (
|
||||
("Run:", self.runCountVar),
|
||||
("Failures:", self.failCountVar),
|
||||
("Errors:", self.errorCountVar),
|
||||
("Remaining:", self.remainingCountVar),
|
||||
):
|
||||
tk.Label(progressFrame, text=label).pack(side=tk.LEFT)
|
||||
tk.Label(progressFrame, textvariable=var,
|
||||
foreground="blue").pack(side=tk.LEFT, fill=tk.X,
|
||||
expand=1, anchor=tk.W)
|
||||
tk.Label(progressFrame, textvariable=var, foreground="blue").pack(
|
||||
side=tk.LEFT, fill=tk.X, expand=1, anchor=tk.W
|
||||
)
|
||||
|
||||
# List box showing errors and failures
|
||||
tk.Label(leftFrame, text="Failures and errors:").pack(anchor=tk.W)
|
||||
listFrame = tk.Frame(leftFrame, relief=tk.SUNKEN, borderwidth=2)
|
||||
listFrame.pack(fill=tk.BOTH, anchor=tk.NW, expand=1)
|
||||
self.errorListbox = tk.Listbox(listFrame, foreground='red',
|
||||
selectmode=tk.SINGLE,
|
||||
selectborderwidth=0)
|
||||
self.errorListbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=1,
|
||||
anchor=tk.NW)
|
||||
self.errorListbox = tk.Listbox(
|
||||
listFrame, foreground="red", selectmode=tk.SINGLE, selectborderwidth=0
|
||||
)
|
||||
self.errorListbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=1, anchor=tk.NW)
|
||||
listScroll = tk.Scrollbar(listFrame, command=self.errorListbox.yview)
|
||||
listScroll.pack(side=tk.LEFT, fill=tk.Y, anchor=tk.N)
|
||||
self.errorListbox.bind("<Double-1>",
|
||||
lambda e, self=self: self.showSelectedError())
|
||||
self.errorListbox.bind("<Double-1>", lambda e, self=self: self.showSelectedError())
|
||||
self.errorListbox.configure(yscrollcommand=listScroll.set)
|
||||
|
||||
|
||||
def getSelectedTestName(self):
|
||||
return self.suiteNameVar.get()
|
||||
|
||||
def errorDialog(self, title, message):
|
||||
tkMessageBox.showerror(parent=self.root, title=title,
|
||||
message=message)
|
||||
tkMessageBox.showerror(parent=self.root, title=title, message=message)
|
||||
|
||||
def notifyRunning(self):
|
||||
self.runCountVar.set(0)
|
||||
@@ -289,15 +293,15 @@ class TkTestRunner(BaseGUITestRunner):
|
||||
self.errorInfo = []
|
||||
while self.errorListbox.size():
|
||||
self.errorListbox.delete(0)
|
||||
#Stopping seems not to work, so simply disable the start button
|
||||
#self.stopGoButton.config(command=self.stopClicked, text="Stop")
|
||||
# Stopping seems not to work, so simply disable the start button
|
||||
# self.stopGoButton.config(command=self.stopClicked, text="Stop")
|
||||
self.stopGoButton.config(state=tk.DISABLED)
|
||||
self.progressBar.setProgressFraction(0.0)
|
||||
self.top.update_idletasks()
|
||||
|
||||
def notifyStopped(self):
|
||||
self.stopGoButton.config(state=tk.ACTIVE)
|
||||
#self.stopGoButton.config(command=self.runClicked, text="Start")
|
||||
# self.stopGoButton.config(command=self.runClicked, text="Start")
|
||||
self.statusVar.set("Idle")
|
||||
|
||||
def notifyTestStarted(self, test):
|
||||
@@ -307,45 +311,42 @@ class TkTestRunner(BaseGUITestRunner):
|
||||
def notifyTestFailed(self, test, err):
|
||||
self.failCountVar.set(1 + self.failCountVar.get())
|
||||
self.errorListbox.insert(tk.END, "Failure: %s" % test)
|
||||
self.errorInfo.append((test,err))
|
||||
self.errorInfo.append((test, err))
|
||||
|
||||
def notifyTestErrored(self, test, err):
|
||||
self.errorCountVar.set(1 + self.errorCountVar.get())
|
||||
self.errorListbox.insert(tk.END, "Error: %s" % test)
|
||||
self.errorInfo.append((test,err))
|
||||
self.errorInfo.append((test, err))
|
||||
|
||||
def notifyTestFinished(self, test):
|
||||
self.remainingCountVar.set(self.remainingCountVar.get() - 1)
|
||||
self.runCountVar.set(1 + self.runCountVar.get())
|
||||
fractionDone = float(self.runCountVar.get())/float(self.totalTests)
|
||||
fractionDone = float(self.runCountVar.get()) / float(self.totalTests)
|
||||
fillColor = len(self.errorInfo) and "red" or "green"
|
||||
self.progressBar.setProgressFraction(fractionDone, fillColor)
|
||||
|
||||
def showAboutDialog(self):
|
||||
tkMessageBox.showinfo(parent=self.root, title="About PyUnit",
|
||||
message=_ABOUT_TEXT)
|
||||
tkMessageBox.showinfo(parent=self.root, title="About PyUnit", message=_ABOUT_TEXT)
|
||||
|
||||
def showHelpDialog(self):
|
||||
tkMessageBox.showinfo(parent=self.root, title="PyUnit help",
|
||||
message=_HELP_TEXT)
|
||||
tkMessageBox.showinfo(parent=self.root, title="PyUnit help", message=_HELP_TEXT)
|
||||
|
||||
def showSelectedError(self):
|
||||
selection = self.errorListbox.curselection()
|
||||
if not selection: return
|
||||
if not selection:
|
||||
return
|
||||
selected = int(selection[0])
|
||||
txt = self.errorListbox.get(selected)
|
||||
window = tk.Toplevel(self.root)
|
||||
window.title(txt)
|
||||
window.protocol('WM_DELETE_WINDOW', window.quit)
|
||||
window.protocol("WM_DELETE_WINDOW", window.quit)
|
||||
test, error = self.errorInfo[selected]
|
||||
tk.Label(window, text=str(test),
|
||||
foreground="red", justify=tk.LEFT).pack(anchor=tk.W)
|
||||
tk.Label(window, text=str(test), foreground="red", justify=tk.LEFT).pack(anchor=tk.W)
|
||||
tracebackLines = traceback.format_exception(*error + (10,))
|
||||
tracebackText = string.join(tracebackLines,'')
|
||||
tracebackText = string.join(tracebackLines, "")
|
||||
tk.Label(window, text=tracebackText, justify=tk.LEFT).pack()
|
||||
tk.Button(window, text="Close",
|
||||
command=window.quit).pack(side=tk.BOTTOM)
|
||||
window.bind('<Key-Return>', lambda e, w=window: w.quit())
|
||||
tk.Button(window, text="Close", command=window.quit).pack(side=tk.BOTTOM)
|
||||
window.bind("<Key-Return>", lambda e, w=window: w.quit())
|
||||
window.mainloop()
|
||||
window.destroy()
|
||||
|
||||
@@ -356,42 +357,44 @@ class ProgressBar(tk.Frame):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
tk.Frame.__init__(*(self,) + args, **kwargs)
|
||||
self.canvas = tk.Canvas(self, height='20', width='60',
|
||||
background='white', borderwidth=3)
|
||||
self.canvas = tk.Canvas(self, height="20", width="60", background="white", borderwidth=3)
|
||||
self.canvas.pack(fill=tk.X, expand=1)
|
||||
self.rect = self.text = None
|
||||
self.canvas.bind('<Configure>', self.paint)
|
||||
self.canvas.bind("<Configure>", self.paint)
|
||||
self.setProgressFraction(0.0)
|
||||
|
||||
def setProgressFraction(self, fraction, color='blue'):
|
||||
def setProgressFraction(self, fraction, color="blue"):
|
||||
self.fraction = fraction
|
||||
self.color = color
|
||||
self.paint()
|
||||
self.canvas.update_idletasks()
|
||||
|
||||
|
||||
def paint(self, *args):
|
||||
totalWidth = self.canvas.winfo_width()
|
||||
width = int(self.fraction * float(totalWidth))
|
||||
height = self.canvas.winfo_height()
|
||||
if self.rect is not None: self.canvas.delete(self.rect)
|
||||
if self.text is not None: self.canvas.delete(self.text)
|
||||
self.rect = self.canvas.create_rectangle(0, 0, width, height,
|
||||
fill=self.color)
|
||||
if self.rect is not None:
|
||||
self.canvas.delete(self.rect)
|
||||
if self.text is not None:
|
||||
self.canvas.delete(self.text)
|
||||
self.rect = self.canvas.create_rectangle(0, 0, width, height, fill=self.color)
|
||||
percentString = "%3.0f%%" % (100.0 * self.fraction)
|
||||
self.text = self.canvas.create_text(totalWidth/2, height/2,
|
||||
anchor=tk.CENTER,
|
||||
text=percentString)
|
||||
self.text = self.canvas.create_text(
|
||||
totalWidth / 2, height / 2, anchor=tk.CENTER, text=percentString
|
||||
)
|
||||
|
||||
|
||||
def main(initialTestName=""):
|
||||
root = tk.Tk()
|
||||
root.title("PyUnit")
|
||||
runner = TkTestRunner(root, initialTestName)
|
||||
root.protocol('WM_DELETE_WINDOW', root.quit)
|
||||
root.protocol("WM_DELETE_WINDOW", root.quit)
|
||||
root.mainloop()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
||||
if len(sys.argv) == 2:
|
||||
main(sys.argv[1])
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user