[Python-checkins] r69042 - in sandbox/trunk/ttk-gsoc/src: 2.x/test/runtests.py 2.x/test/support.py 2.x/test/test_extensions.py 2.x/test/test_functions.py 2.x/test/test_style.py 2.x/test/test_widgets.py 2.x/ttk.py 3.x/test/runtests.py 3.x/test/support.py 3.x/test/test_extensions.py 3.x/test/test_functions.py 3.x/test/test_style.py 3.x/test/test_widgets.py 3.x/ttk.py

guilherme.polo python-checkins at python.org
Wed Jan 28 00:48:31 CET 2009


Author: guilherme.polo
Date: Wed Jan 28 00:48:30 2009
New Revision: 69042

Log:
* Update tests to use Python's test support where possible;
* Fixed some issues found in tests;
* Fixed a bug in LabeledScale.destroy.


Modified:
   sandbox/trunk/ttk-gsoc/src/2.x/test/runtests.py
   sandbox/trunk/ttk-gsoc/src/2.x/test/support.py
   sandbox/trunk/ttk-gsoc/src/2.x/test/test_extensions.py
   sandbox/trunk/ttk-gsoc/src/2.x/test/test_functions.py
   sandbox/trunk/ttk-gsoc/src/2.x/test/test_style.py
   sandbox/trunk/ttk-gsoc/src/2.x/test/test_widgets.py
   sandbox/trunk/ttk-gsoc/src/2.x/ttk.py
   sandbox/trunk/ttk-gsoc/src/3.x/test/runtests.py
   sandbox/trunk/ttk-gsoc/src/3.x/test/support.py
   sandbox/trunk/ttk-gsoc/src/3.x/test/test_extensions.py
   sandbox/trunk/ttk-gsoc/src/3.x/test/test_functions.py
   sandbox/trunk/ttk-gsoc/src/3.x/test/test_style.py
   sandbox/trunk/ttk-gsoc/src/3.x/test/test_widgets.py
   sandbox/trunk/ttk-gsoc/src/3.x/ttk.py

Modified: sandbox/trunk/ttk-gsoc/src/2.x/test/runtests.py
==============================================================================
--- sandbox/trunk/ttk-gsoc/src/2.x/test/runtests.py	(original)
+++ sandbox/trunk/ttk-gsoc/src/2.x/test/runtests.py	Wed Jan 28 00:48:30 2009
@@ -1,39 +1,25 @@
 import os
 import sys
-import _tkinter
+import unittest
+import test.test_support
 
-# tests in the following modules do not require a running GUI
-TEXTONLY = ('test_functions.py', )
+this_dir_path = os.path.abspath(os.path.dirname(__file__))
 
-def show_tcl_tk():
-    tk_ver = _tkinter.TK_VERSION
-    print "Tcl %s, Tk %s" % (_tkinter.TCL_VERSION, tk_ver)
-    if float(tk_ver) < 8.5:
-        print "Will run tests using tile"
-
-def get_tests(gui_tests=True):
-    testdir = os.path.dirname(sys.argv[0]) or os.curdir
-    extension = ".py"
-    for testname in os.listdir(testdir):
-        if testname.startswith('test_') and testname.endswith(extension):
-            if not gui_tests and testname not in TEXTONLY:
-                continue
-            yield testname[:-len(extension)]
-
-def run_tests(tests):
-    for test in tests:
-        module = __import__(test)
-        getattr(module, "test_main", None)()
-
-def main(args):
-    gui_tests = False
-    if 'DISPLAY' in os.environ or (len(args) > 1 and "-g" in args):
-        gui_tests = True
-
-    show_tcl_tk()
-    run_tests(get_tests(gui_tests))
-    if not gui_tests:
-        print "\n** GUI tests didn't run **"
+def get_tests_modules(path=this_dir_path):
+    """This will import and yield modules whose names start with test_
+    and are inside packages found in path."""
+    py_ext = '.py'
+
+    for name in os.listdir(path):
+        if name.startswith('test_') and name.endswith(py_ext):
+            yield __import__(name[:-len(py_ext)])
+
+def get_tests():
+    """Yield all the tests in the modules found by get_tests_modules."""
+    for module in get_tests_modules():
+        for test in getattr(module, 'tests'):
+            yield test
 
 if __name__ == "__main__":
-    main(sys.argv)
+    test.test_support.use_resources = ['gui']
+    test.test_support.run_unittest(*get_tests())

Modified: sandbox/trunk/ttk-gsoc/src/2.x/test/support.py
==============================================================================
--- sandbox/trunk/ttk-gsoc/src/2.x/test/support.py	(original)
+++ sandbox/trunk/ttk-gsoc/src/2.x/test/support.py	Wed Jan 28 00:48:30 2009
@@ -1,21 +1,20 @@
-import sys
-import unittest
-import _tkinter
+import Tkinter
 
-def run(*classes):
-    suite = unittest.TestSuite()
-    for cls in classes:
-        suite.addTest(unittest.makeSuite(cls))
+def get_tk_root():
+    try:
+        root = Tkinter._default_root
+    except AttributeError:
+        # it is possible to disable default root in Tkinter, although
+        # I haven't seen people doing it (but apparently someone did it
+        # here).
+        root = None
 
-    if '-v' in sys.argv:
-        verbosity = 1
-    elif '-vv' in sys.argv:
-        verbosity = 2
-    else:
-        verbosity = 0
+    if root is None:
+        # create a new master only if there isn't one already
+        root = Tkinter.Tk()
+
+    return root
 
-    runner = unittest.TextTestRunner(sys.stdout, verbosity=verbosity)
-    runner.run(suite)
 
 def simulate_mouse_click(widget, x, y):
     """Generate proper events to click at the x, y position (tries to act

Modified: sandbox/trunk/ttk-gsoc/src/2.x/test/test_extensions.py
==============================================================================
--- sandbox/trunk/ttk-gsoc/src/2.x/test/test_extensions.py	(original)
+++ sandbox/trunk/ttk-gsoc/src/2.x/test/test_extensions.py	Wed Jan 28 00:48:30 2009
@@ -2,9 +2,12 @@
 import unittest
 import Tkinter
 import ttk
+from test.test_support import requires, run_unittest
 
 import support
 
+requires('gui')
+
 class LabeledScaleTest(unittest.TestCase):
 
     def test_widget_destroy(self):
@@ -170,20 +173,21 @@
 
 
 class OptionMenuTest(unittest.TestCase):
-    # XXX Since a StringVar is being created without an explict master, this
-    #   test case can't be the first one to run.
 
     def setUp(self):
-        self.textvar = Tkinter.StringVar()
+        self.root = support.get_tk_root()
+        self.textvar = Tkinter.StringVar(self.root)
 
     def tearDown(self):
         del self.textvar
+        self.root.destroy()
 
 
     def test_widget_destroy(self):
         var = Tkinter.StringVar()
         optmenu = ttk.OptionMenu(None, var)
         name = var._name
+        optmenu.update_idletasks()
         optmenu.destroy()
         self.failUnlessEqual(optmenu.tk.globalgetvar(name), var.get())
         del var
@@ -256,8 +260,7 @@
         optmenu.destroy()
 
 
-def test_main():
-    support.run(LabeledScaleTest, OptionMenuTest)
+tests = [LabeledScaleTest, OptionMenuTest]
 
 if __name__ == "__main__":
-    test_main()
+    run_unittest(*tests)

Modified: sandbox/trunk/ttk-gsoc/src/2.x/test/test_functions.py
==============================================================================
--- sandbox/trunk/ttk-gsoc/src/2.x/test/test_functions.py	(original)
+++ sandbox/trunk/ttk-gsoc/src/2.x/test/test_functions.py	Wed Jan 28 00:48:30 2009
@@ -3,8 +3,6 @@
 import unittest
 import ttk
 
-import support
-
 class MockTclObj(object):
     typename = 'test'
 
@@ -421,9 +419,8 @@
         self.failUnlessEqual(ttk.tclobjs_to_py({'text': 'some text'}),
             {'text': 'some text'})
 
-
-def test_main():
-    support.run(InternalFunctionsTest, TclObjsToPyTest)
+tests = [InternalFunctionsTest, TclObjsToPyTest]
 
 if __name__ == "__main__":
-    test_main()
+    from test.test_support import run_unittest
+    run_unittest(*tests)

Modified: sandbox/trunk/ttk-gsoc/src/2.x/test/test_style.py
==============================================================================
--- sandbox/trunk/ttk-gsoc/src/2.x/test/test_style.py	(original)
+++ sandbox/trunk/ttk-gsoc/src/2.x/test/test_style.py	Wed Jan 28 00:48:30 2009
@@ -1,17 +1,24 @@
 import unittest
 import Tkinter
 import ttk
+from test.test_support import requires, run_unittest
 
 import support
 
+requires('gui')
+
 class StyleTest(unittest.TestCase):
 
     def setUp(self):
-        root = Tkinter.Tk()
-        self.style = ttk.Style(root)
+        self.root = support.get_tk_root()
+        self.style = ttk.Style(self.root)
 
     def tearDown(self):
-        self.style.master.destroy()
+        # As tests have shown, these tests are likely to deliver
+        # <<ThemeChanged>> events after the root is destroyed, so
+        # lets let them happen now.
+        self.root.update_idletasks()
+        self.root.destroy()
 
 
     def test_configure(self):
@@ -86,8 +93,7 @@
         self.style.theme_use(curr_theme)
 
 
-def test_main():
-    support.run(StyleTest)
+tests = [StyleTest]
 
 if __name__ == "__main__":
-    test_main()
+    run_unittest(*tests)

Modified: sandbox/trunk/ttk-gsoc/src/2.x/test/test_widgets.py
==============================================================================
--- sandbox/trunk/ttk-gsoc/src/2.x/test/test_widgets.py	(original)
+++ sandbox/trunk/ttk-gsoc/src/2.x/test/test_widgets.py	Wed Jan 28 00:48:30 2009
@@ -1,10 +1,13 @@
 import unittest
 import Tkinter
 import ttk
+from test.test_support import requires, run_unittest
 
 import support
 from test_functions import MockTclObj, MockStateSpec
 
+requires('gui')
+
 class WidgetTest(unittest.TestCase):
     """Tests methods available in every ttk widget."""
 
@@ -1102,10 +1105,9 @@
         self.failUnless(isinstance(self.tv.tag_configure('test'), dict))
 
 
-def test_main():
-    support.run(WidgetTest, ButtonTest, CheckbuttonTest, RadiobuttonTest,
+tests = [WidgetTest, ButtonTest, CheckbuttonTest, RadiobuttonTest,
         ComboboxTest, EntryTest, PanedwindowTest, ScaleTest, NotebookTest,
-        TreeviewTest)
+        TreeviewTest]
 
 if __name__ == "__main__":
-    test_main()
+    run_unittest(*tests)

Modified: sandbox/trunk/ttk-gsoc/src/2.x/ttk.py
==============================================================================
--- sandbox/trunk/ttk-gsoc/src/2.x/ttk.py	(original)
+++ sandbox/trunk/ttk-gsoc/src/2.x/ttk.py	Wed Jan 28 00:48:30 2009
@@ -51,8 +51,12 @@
 
     return _wrapper
 
+# Store the original Tkinter.Tk._loadtk before replacing it just in case
+# someone wants to restore it.
+__loadtk__ = Tkinter.Tk._loadtk
 Tkinter.Tk._loadtk = _loadttk(Tkinter.Tk._loadtk)
 
+
 def _format_optdict(optdict, script=False, ignore=None):
     """Formats optdict to a tuple to pass it to tk.call.
     
@@ -1521,9 +1525,14 @@
 
     def destroy(self):
         """Destroy this widget and possibly its associated variable."""
-        self._variable.trace_vdelete('w', self.__tracecb)
-        del self._variable
-        Frame.destroy(self)
+        try:
+            self._variable.trace_vdelete('w', self.__tracecb)
+        except AttributeError:
+            # widget has been destroyed already
+            pass
+        else:
+            del self._variable
+            Frame.destroy(self)
 
 
     def _adjust(self, *args):

Modified: sandbox/trunk/ttk-gsoc/src/3.x/test/runtests.py
==============================================================================
--- sandbox/trunk/ttk-gsoc/src/3.x/test/runtests.py	(original)
+++ sandbox/trunk/ttk-gsoc/src/3.x/test/runtests.py	Wed Jan 28 00:48:30 2009
@@ -1,39 +1,25 @@
 import os
 import sys
-import _tkinter
+import unittest
+import test.support
 
-# tests in the following modules do not require a running GUI
-TEXTONLY = ('test_functions.py', )
+this_dir_path = os.path.abspath(os.path.dirname(__file__))
 
-def show_tcl_tk():
-    tk_ver = _tkinter.TK_VERSION
-    print("Tcl %s, Tk %s" % (_tkinter.TCL_VERSION, tk_ver))
-    if float(tk_ver) < 8.5:
-        print("Will run tests using tile")
-
-def get_tests(gui_tests=True):
-    testdir = os.path.dirname(sys.argv[0]) or os.curdir
-    extension = ".py"
-    for testname in os.listdir(testdir):
-        if testname.startswith('test_') and testname.endswith(extension):
-            if not gui_tests and testname not in TEXTONLY:
-                continue
-            yield testname[:-len(extension)]
-
-def run_tests(tests):
-    for test in tests:
-        module = __import__(test)
-        getattr(module, "test_main", None)()
-
-def main(args):
-    gui_tests = False
-    if 'DISPLAY' in os.environ or (len(args) > 1 and "-g" in args):
-        gui_tests = True
-
-    show_tcl_tk()
-    run_tests(get_tests(gui_tests))
-    if not gui_tests:
-        print("\n** GUI tests didn't run **")
+def get_tests_modules(path=this_dir_path):
+    """This will import and yield modules whose names start with test_
+    and are inside packages found in path."""
+    py_ext = '.py'
+
+    for name in os.listdir(path):
+        if name.startswith('test_') and name.endswith(py_ext):
+            yield __import__(name[:-len(py_ext)])
+
+def get_tests():
+    """Yield all the tests in the modules found by get_tests_modules."""
+    for module in get_tests_modules():
+        for test in getattr(module, 'tests'):
+            yield test
 
 if __name__ == "__main__":
-    main(sys.argv)
+    test.support.use_resources = ['gui']
+    test.support.run_unittest(*get_tests())

Modified: sandbox/trunk/ttk-gsoc/src/3.x/test/support.py
==============================================================================
--- sandbox/trunk/ttk-gsoc/src/3.x/test/support.py	(original)
+++ sandbox/trunk/ttk-gsoc/src/3.x/test/support.py	Wed Jan 28 00:48:30 2009
@@ -1,20 +1,20 @@
-import sys
-import unittest
+import tkinter
 
-def run(*classes):
-    suite = unittest.TestSuite()
-    for cls in classes:
-        suite.addTest(unittest.makeSuite(cls))
+def get_tk_root():
+    try:
+        root = tkinter._default_root
+    except AttributeError:
+        # it is possible to disable default root in Tkinter, although
+        # I haven't seen people doing it (but apparently someone did it
+        # here).
+        root = None
 
-    if '-v' in sys.argv:
-        verbosity = 1
-    elif '-vv' in sys.argv:
-        verbosity = 2
-    else:
-        verbosity = 0
+    if root is None:
+        # create a new master only if there isn't one already
+        root = tkinter.Tk()
+
+    return root
 
-    runner = unittest.TextTestRunner(sys.stdout, verbosity=verbosity)
-    runner.run(suite)
 
 def simulate_mouse_click(widget, x, y):
     """Generate proper events to click at the x, y position (tries to act

Modified: sandbox/trunk/ttk-gsoc/src/3.x/test/test_extensions.py
==============================================================================
--- sandbox/trunk/ttk-gsoc/src/3.x/test/test_extensions.py	(original)
+++ sandbox/trunk/ttk-gsoc/src/3.x/test/test_extensions.py	Wed Jan 28 00:48:30 2009
@@ -2,9 +2,12 @@
 import unittest
 import tkinter
 import ttk
+from test.support import requires, run_unittest
 
 import support
 
+requires('gui')
+
 class LabeledScaleTest(unittest.TestCase):
 
     def test_widget_destroy(self):
@@ -170,20 +173,21 @@
 
 
 class OptionMenuTest(unittest.TestCase):
-    # XXX Since a StringVar is being created without an explict master, this
-    #   test case can't be the first one to run.
 
     def setUp(self):
-        self.textvar = tkinter.StringVar()
+        self.root = support.get_tk_root()
+        self.textvar = tkinter.StringVar(self.root)
 
     def tearDown(self):
         del self.textvar
+        self.root.destroy()
 
 
     def test_widget_destroy(self):
         var = tkinter.StringVar()
         optmenu = ttk.OptionMenu(None, var)
         name = var._name
+        optmenu.update_idletasks()
         optmenu.destroy()
         self.failUnlessEqual(optmenu.tk.globalgetvar(name), var.get())
         del var
@@ -256,8 +260,7 @@
         optmenu.destroy()
 
 
-def test_main():
-    support.run(LabeledScaleTest, OptionMenuTest)
+tests = [LabeledScaleTest, OptionMenuTest]
 
 if __name__ == "__main__":
-    test_main()
+    run_unittest(*tests)

Modified: sandbox/trunk/ttk-gsoc/src/3.x/test/test_functions.py
==============================================================================
--- sandbox/trunk/ttk-gsoc/src/3.x/test/test_functions.py	(original)
+++ sandbox/trunk/ttk-gsoc/src/3.x/test/test_functions.py	Wed Jan 28 00:48:30 2009
@@ -2,8 +2,6 @@
 import unittest
 import ttk
 
-import support
-
 class MockTclObj(object):
     typename = 'test'
 
@@ -418,9 +416,8 @@
         self.failUnlessEqual(ttk.tclobjs_to_py({'text': 'some text'}),
             {'text': 'some text'})
 
-
-def test_main():
-    support.run(InternalFunctionsTest, TclObjsToPyTest)
+tests = [InternalFunctionsTest, TclObjsToPyTest]
 
 if __name__ == "__main__":
-    test_main()
+    from test.support import run_unittest
+    run_unittest(*tests)

Modified: sandbox/trunk/ttk-gsoc/src/3.x/test/test_style.py
==============================================================================
--- sandbox/trunk/ttk-gsoc/src/3.x/test/test_style.py	(original)
+++ sandbox/trunk/ttk-gsoc/src/3.x/test/test_style.py	Wed Jan 28 00:48:30 2009
@@ -1,17 +1,24 @@
 import unittest
 import tkinter
 import ttk
+from test.support import requires, run_unittest
 
 import support
 
+requires('gui')
+
 class StyleTest(unittest.TestCase):
 
     def setUp(self):
-        root = tkinter.Tk()
-        self.style = ttk.Style(root)
+        self.root = support.get_tk_root()
+        self.style = ttk.Style(self.root)
 
     def tearDown(self):
-        self.style.master.destroy()
+        # As tests have shown, these tests are likely to deliver
+        # <<ThemeChanged>> events after the root is destroyed, so
+        # lets let them happen now.
+        self.root.update_idletasks()
+        self.root.destroy()
 
 
     def test_configure(self):
@@ -86,8 +93,7 @@
         self.style.theme_use(curr_theme)
 
 
-def test_main():
-    support.run(StyleTest)
+tests = [StyleTest]
 
 if __name__ == "__main__":
-    test_main()
+    run_unittest(*tests)

Modified: sandbox/trunk/ttk-gsoc/src/3.x/test/test_widgets.py
==============================================================================
--- sandbox/trunk/ttk-gsoc/src/3.x/test/test_widgets.py	(original)
+++ sandbox/trunk/ttk-gsoc/src/3.x/test/test_widgets.py	Wed Jan 28 00:48:30 2009
@@ -1,10 +1,13 @@
 import unittest
 import tkinter
 import ttk
+from test.support import requires, run_unittest
 
 import support
 from test_functions import MockTclObj, MockStateSpec
 
+requires('gui')
+
 class WidgetTest(unittest.TestCase):
     """Tests methods available in every ttk widget."""
 
@@ -1102,10 +1105,9 @@
         self.failUnless(isinstance(self.tv.tag_configure('test'), dict))
 
 
-def test_main():
-    support.run(WidgetTest, ButtonTest, CheckbuttonTest, RadiobuttonTest,
+tests = [WidgetTest, ButtonTest, CheckbuttonTest, RadiobuttonTest,
         ComboboxTest, EntryTest, PanedwindowTest, ScaleTest, NotebookTest,
-        TreeviewTest)
+        TreeviewTest]
 
 if __name__ == "__main__":
-    test_main()
+    run_unittest(*tests)

Modified: sandbox/trunk/ttk-gsoc/src/3.x/ttk.py
==============================================================================
--- sandbox/trunk/ttk-gsoc/src/3.x/ttk.py	(original)
+++ sandbox/trunk/ttk-gsoc/src/3.x/ttk.py	Wed Jan 28 00:48:30 2009
@@ -51,8 +51,12 @@
 
     return _wrapper
 
+# Store the original tkinter.Tk._loadtk before replacing it just in case
+# someone wants to restore it.
+__loadtk__ = tkinter.Tk._loadtk
 tkinter.Tk._loadtk = _loadttk(tkinter.Tk._loadtk)
 
+
 def _format_optdict(optdict, script=False, ignore=None):
     """Formats optdict to a tuple to pass it to tk.call.
     
@@ -1521,9 +1525,14 @@
 
     def destroy(self):
         """Destroy this widget and possibly its associated variable."""
-        self._variable.trace_vdelete('w', self.__tracecb)
-        del self._variable
-        Frame.destroy(self)
+        try:
+            self._variable.trace_vdelete('w', self.__tracecb)
+        except AttributeError:
+            # widget has been destroyed already
+            pass
+        else:
+            del self._variable
+            Frame.destroy(self)
 
 
     def _adjust(self, *args):


More information about the Python-checkins mailing list