From ef5d723314308627567c85e213dc0abc18568b2b Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Wed, 27 May 2020 17:34:39 +0100 Subject: [PATCH 1/4] Add tests for any non-null toolkit for layout and labels --- traitsui/tests/_tools.py | 24 ++++++++++++++++ traitsui/tests/test_labels.py | 52 ++++++++++++++++++++++++----------- traitsui/tests/test_layout.py | 48 +++++++++++++++++++++++++++----- 3 files changed, 101 insertions(+), 23 deletions(-) diff --git a/traitsui/tests/_tools.py b/traitsui/tests/_tools.py index a46047e3b..3da103444 100644 --- a/traitsui/tests/_tools.py +++ b/traitsui/tests/_tools.py @@ -131,6 +131,30 @@ def filter_tests(test_suite, exclusion_pattern): return filtered_test_suite +@contextmanager +def create_ui(object, ui_kwargs=None): + """ Context manager for creating a UI and then dispose it when exiting + the context. + + Parameters + ---------- + object : HasTraits + An object from which ``edit_traits`` can be called to create a UI + ui_kwargs : dict or None + Keyword arguments to be provided to ``edit_traits``. + + Yields + ------ + ui: UI + """ + ui_kwargs = {} if ui_kwargs is None else ui_kwargs + ui = object.edit_traits(**ui_kwargs) + try: + yield ui + finally: + ui.dispose() + + # ######### Utility tools to test on both qt4 and wx diff --git a/traitsui/tests/test_labels.py b/traitsui/tests/test_labels.py index 4a49b572f..7bf0bbfbe 100644 --- a/traitsui/tests/test_labels.py +++ b/traitsui/tests/test_labels.py @@ -25,6 +25,7 @@ from traitsui.group import VGroup, HGroup from traitsui.tests._tools import ( + create_ui, is_current_backend_qt4, is_current_backend_wx, skip_if_not_qt4, @@ -166,9 +167,8 @@ def _test_qt_labels_right_resizing(self, dialog_class): from pyface import qt - with store_exceptions_on_all_threads(): - dialog = dialog_class() - ui = dialog.edit_traits() + with store_exceptions_on_all_threads(), \ + create_ui(dialog_class()) as ui: # all labels labels = ui.control.findChildren(qt.QtGui.QLabel) @@ -206,23 +206,13 @@ def test_qt_labels_right_resizing_vertical(self): def test_qt_labels_right_resizing_horizontal(self): self._test_qt_labels_right_resizing(HResizeTestDialog) - @skip_if_not_qt4 - def test_qt_no_labels_on_the_right_bug(self): - # Bug: If one set show_left=False, show_label=False on a non-resizable - # item like a checkbox, the Qt backend tried to set the label's size - # policy and failed because label=None. - - with store_exceptions_on_all_threads(): - dialog = NoLabelResizeTestDialog() - ui = dialog.edit_traits() - @skip_if_null def test_labels_enabled_when(self): # Behaviour: label should enable/disable along with editor - with store_exceptions_on_all_threads(): - dialog = EnableWhenDialog() - ui = dialog.edit_traits() + dialog = EnableWhenDialog() + with store_exceptions_on_all_threads(), \ + create_ui(dialog) as ui: labelled_editor = ui.get_editors("labelled_item")[0] @@ -241,6 +231,36 @@ def test_labels_enabled_when(self): ui.dispose() +@skip_if_null +class TestAnyToolkit(unittest.TestCase): + """ Toolkit-agnostic tests for labels with different orientations.""" + + def test_group_show_right_labels(self): + with store_exceptions_on_all_threads(), \ + create_ui(ShowRightLabelsDialog()): + pass + + def test_horizontal_resizable_and_labels(self): + with store_exceptions_on_all_threads(), \ + create_ui(HResizeTestDialog()): + pass + + def test_all_resizable_with_labels(self): + with store_exceptions_on_all_threads(), \ + create_ui(VResizeTestDialog()): + pass + + def test_show_right_with_no_label(self): + with store_exceptions_on_all_threads(), \ + create_ui(NoLabelResizeTestDialog()): + pass + + def test_enable_when_flag(self): + with store_exceptions_on_all_threads(), \ + create_ui(EnableWhenDialog()): + pass + + if __name__ == "__main__": # Execute from command line for manual testing vw = HResizeTestDialog() diff --git a/traitsui/tests/test_layout.py b/traitsui/tests/test_layout.py index 33df35efc..4adfb57aa 100644 --- a/traitsui/tests/test_layout.py +++ b/traitsui/tests/test_layout.py @@ -27,7 +27,9 @@ from traitsui.group import HGroup, VGroup from traitsui.tests._tools import ( + create_ui, skip_if_not_qt4, + skip_if_null, store_exceptions_on_all_threads, ) @@ -37,6 +39,13 @@ _TXT_WIDTH = 100 +class MultipleTrait(HasTraits): + """ An object with multiple traits to test layout and alignments.""" + + txt1 = Str("text1") + txt2 = Str("text2") + + class VResizeDialog(HasTraits): txt = Str("hallo") @@ -71,10 +80,8 @@ def test_qt_resizable_in_vgroup(self): from pyface import qt - with store_exceptions_on_all_threads(): - dialog = VResizeDialog() - ui = dialog.edit_traits() - + with store_exceptions_on_all_threads(), \ + create_ui(VResizeDialog()) as ui: text = ui.control.findChild(qt.QtGui.QLineEdit) # horizontal size should be large @@ -91,9 +98,8 @@ def test_qt_resizable_in_hgroup(self): from pyface import qt - with store_exceptions_on_all_threads(): - dialog = HResizeDialog() - ui = dialog.edit_traits() + with store_exceptions_on_all_threads(), \ + create_ui(HResizeDialog()) as ui: text = ui.control.findChild(qt.QtGui.QLineEdit) @@ -106,6 +112,34 @@ def test_qt_resizable_in_hgroup(self): # self.assertLess(text.width(), _TXT_WIDTH+100) +@skip_if_null +class TestOrientation(unittest.TestCase): + """ Toolkit-agnostic tests on the layout orientations.""" + + def test_vertical_layout(self): + view = View( + VGroup( + Item("txt1"), + Item("txt2"), + ) + ) + with store_exceptions_on_all_threads(), \ + create_ui(MultipleTrait(), ui_kwargs=dict(view=view)): + pass + + def test_horizontal_layout(self): + # layout + view = View( + HGroup( + Item("txt1"), + Item("txt2"), + ) + ) + with store_exceptions_on_all_threads(), \ + create_ui(MultipleTrait(), ui_kwargs=dict(view=view)): + pass + + if __name__ == "__main__": # Execute from command line for manual testing vw = VResizeDialog() From 72eddc2453d048ed6bcf572951983e5071ce5927 Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Wed, 27 May 2020 17:36:31 +0100 Subject: [PATCH 2/4] Restore previous comment --- traitsui/tests/test_labels.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/traitsui/tests/test_labels.py b/traitsui/tests/test_labels.py index 7bf0bbfbe..17b2ea9a2 100644 --- a/traitsui/tests/test_labels.py +++ b/traitsui/tests/test_labels.py @@ -251,6 +251,9 @@ def test_all_resizable_with_labels(self): pass def test_show_right_with_no_label(self): + # Bug: If one set show_left=False, show_label=False on a non-resizable + # item like a checkbox, the Qt backend tried to set the label's size + # policy and failed because label=None. with store_exceptions_on_all_threads(), \ create_ui(NoLabelResizeTestDialog()): pass From 2d9c4a708dab605ac2c783e8013511fd18cd0772 Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Mon, 1 Jun 2020 14:46:37 +0100 Subject: [PATCH 3/4] Replace findChild with get_editors --- traitsui/tests/test_layout.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/traitsui/tests/test_layout.py b/traitsui/tests/test_layout.py index 4adfb57aa..1a5103c39 100644 --- a/traitsui/tests/test_layout.py +++ b/traitsui/tests/test_layout.py @@ -82,7 +82,8 @@ def test_qt_resizable_in_vgroup(self): with store_exceptions_on_all_threads(), \ create_ui(VResizeDialog()) as ui: - text = ui.control.findChild(qt.QtGui.QLineEdit) + editor, = ui.get_editors("txt") + text = editor.control # horizontal size should be large self.assertGreater(text.width(), _DIALOG_WIDTH - 100) @@ -101,7 +102,8 @@ def test_qt_resizable_in_hgroup(self): with store_exceptions_on_all_threads(), \ create_ui(HResizeDialog()) as ui: - text = ui.control.findChild(qt.QtGui.QLineEdit) + editor, = ui.get_editors("txt") + text = editor.control # vertical size should be large self.assertGreater(text.height(), _DIALOG_HEIGHT - 100) From 5217ebf2f73715032f3f5408dc2e90622d57565f Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Mon, 1 Jun 2020 17:30:44 +0100 Subject: [PATCH 4/4] Call create_ui in another test where the UI is not closed --- traitsui/tests/test_labels.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/traitsui/tests/test_labels.py b/traitsui/tests/test_labels.py index dc3895acc..35c01b957 100644 --- a/traitsui/tests/test_labels.py +++ b/traitsui/tests/test_labels.py @@ -133,10 +133,9 @@ def test_qt_show_labels_right_without_colon(self): # that are shown to the *right* of the corresponding elements from pyface import qt - - with store_exceptions_on_all_threads(): - dialog = ShowRightLabelsDialog() - ui = dialog.edit_traits() + dialog = ShowRightLabelsDialog() + with store_exceptions_on_all_threads(), \ + create_ui(dialog) as ui: # get reference to label objects labels = ui.control.findChildren(qt.QtGui.QLabel)