From 4d984fa098f1849618c4336243cfae19bfb4a1dc Mon Sep 17 00:00:00 2001 From: "C.A.M. Gerlach" Date: Sat, 10 Mar 2018 15:00:51 -0600 Subject: [PATCH 1/3] Increase timeouts on two tests so they pass more reliably --- spyder/app/tests/test_mainwindow.py | 9 +++++---- spyder/plugins/tests/test_ipythonconsole.py | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/spyder/app/tests/test_mainwindow.py b/spyder/app/tests/test_mainwindow.py index 14921941e88..f961fc50f81 100644 --- a/spyder/app/tests/test_mainwindow.py +++ b/spyder/app/tests/test_mainwindow.py @@ -221,7 +221,8 @@ def test_get_help(main_window, qtbot): """ shell = main_window.ipyconsole.get_current_shellwidget() control = shell._control - qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) + qtbot.waitUntil(lambda: shell._prompt_html is not None, + timeout=SHELL_TIMEOUT) help_plugin = main_window.help webview = help_plugin.rich_text.webview._webview @@ -238,10 +239,10 @@ def test_get_help(main_window, qtbot): control.inspect_current_object() # Check that a expected text is part of the page - qtbot.waitUntil(lambda: check_text(webpage, "namespace"), timeout=4000) + qtbot.waitUntil(lambda: check_text(webpage, "namespace"), timeout=6000) # --- From the editor --- - qtbot.wait(2000) + qtbot.wait(3000) main_window.editor.new() code_editor = main_window.editor.get_focus_widget() editorstack = main_window.editor.get_current_editorstack() @@ -254,7 +255,7 @@ def test_get_help(main_window, qtbot): editorstack.inspect_current_object() # Check that a expected text is part of the page - qtbot.waitUntil(lambda: check_text(webpage, "range"), timeout=4000) + qtbot.waitUntil(lambda: check_text(webpage, "range"), timeout=6000) @pytest.mark.slow diff --git a/spyder/plugins/tests/test_ipythonconsole.py b/spyder/plugins/tests/test_ipythonconsole.py index 3f8a48d4bef..362e3b357c6 100644 --- a/spyder/plugins/tests/test_ipythonconsole.py +++ b/spyder/plugins/tests/test_ipythonconsole.py @@ -832,17 +832,17 @@ def test_set_elapsed_time(ipyconsole, qtbot): # Set time to 2 minutes ago. client.t0 -= 120 - with qtbot.waitSignal(client.timer.timeout, timeout=3000): + with qtbot.waitSignal(client.timer.timeout, timeout=5000): ipyconsole.set_elapsed_time(client) assert '00:02:00' in client.time_label.text() - with qtbot.waitSignal(client.timer.timeout, timeout=3000): + with qtbot.waitSignal(client.timer.timeout, timeout=5000): pass assert '00:02:01' in client.time_label.text() # Make previous time later than current time. client.t0 += 2000 - with qtbot.waitSignal(client.timer.timeout, timeout=3000): + with qtbot.waitSignal(client.timer.timeout, timeout=5000): pass assert '00:00:00' in client.time_label.text() From dcd35a49c07ed263ecda4651acce7cb4e041e39c Mon Sep 17 00:00:00 2001 From: "C.A.M. Gerlach" Date: Sat, 10 Mar 2018 15:02:21 -0600 Subject: [PATCH 2/3] Tweak arrayeditor and dfeditor interactive tests for reliability --- .../tests/test_arrayeditor.py | 18 +++---- .../tests/test_dataframeeditor.py | 48 ++++++++++--------- 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/spyder/widgets/variableexplorer/tests/test_arrayeditor.py b/spyder/widgets/variableexplorer/tests/test_arrayeditor.py index c0f12f01592..37d9cecc80f 100644 --- a/spyder/widgets/variableexplorer/tests/test_arrayeditor.py +++ b/spyder/widgets/variableexplorer/tests/test_arrayeditor.py @@ -232,20 +232,22 @@ def test_arrayeditor_edit_overflow(qtbot, monkeypatch): qtbot.waitForWindowShown(dialog) view = dialog.arraywidget.view - qtbot.keyPress(view, Qt.Key_Down) - qtbot.keyPress(view, Qt.Key_Up) + qtbot.keyClick(view, Qt.Key_Down) + qtbot.keyClick(view, Qt.Key_Up) qtbot.keyClicks(view, '5') - qtbot.keyPress(view, Qt.Key_Down) - qtbot.keyPress(view, Qt.Key_Space) + qtbot.keyClick(view, Qt.Key_Down) + qtbot.keyClick(view, Qt.Key_Space) qtbot.keyClicks(view.focusWidget(), str(int(2 ** bit_exponent))) - qtbot.keyPress(view.focusWidget(), Qt.Key_Down) + qtbot.keyClick(view.focusWidget(), Qt.Key_Down) MockQMessageBox.critical.assert_called_with(ANY, "Error", ANY) assert MockQMessageBox.critical.call_count == idx qtbot.keyClicks(view, '7') - qtbot.keyPress(view, Qt.Key_Up) + qtbot.keyClick(view, Qt.Key_Up) qtbot.keyClicks(view, '6') - qtbot.keyPress(view, Qt.Key_Down) - qtbot.keyPress(view, Qt.Key_Return) + qtbot.keyClick(view, Qt.Key_Down) + qtbot.wait(200) + dialog.accept() + qtbot.wait(500) assert np.sum(expected_array == dialog.get_value()) == len(expected_array) diff --git a/spyder/widgets/variableexplorer/tests/test_dataframeeditor.py b/spyder/widgets/variableexplorer/tests/test_dataframeeditor.py index a6746afd671..45d98c483da 100644 --- a/spyder/widgets/variableexplorer/tests/test_dataframeeditor.py +++ b/spyder/widgets/variableexplorer/tests/test_dataframeeditor.py @@ -326,20 +326,22 @@ def test_dataframeeditor_edit_overflow(qtbot, monkeypatch): qtbot.waitForWindowShown(dialog) view = dialog.dataTable - qtbot.keyPress(view, Qt.Key_Right) + qtbot.keyClick(view, Qt.Key_Right) qtbot.keyClicks(view, '5') - qtbot.keyPress(view, Qt.Key_Down) - qtbot.keyPress(view, Qt.Key_Space) - qtbot.keyPress(view.focusWidget(), Qt.Key_Backspace) + qtbot.keyClick(view, Qt.Key_Down) + qtbot.keyClick(view, Qt.Key_Space) + qtbot.keyClick(view.focusWidget(), Qt.Key_Backspace) qtbot.keyClicks(view.focusWidget(), str(int(2 ** bit_exponet))) - qtbot.keyPress(view.focusWidget(), Qt.Key_Down) + qtbot.keyClick(view.focusWidget(), Qt.Key_Down) MockQMessageBox.critical.assert_called_with(ANY, "Error", ANY) assert MockQMessageBox.critical.call_count == idx qtbot.keyClicks(view, '7') - qtbot.keyPress(view, Qt.Key_Up) + qtbot.keyClick(view, Qt.Key_Up) qtbot.keyClicks(view, '6') - qtbot.keyPress(view, Qt.Key_Down) - qtbot.keyPress(view, Qt.Key_Return) + qtbot.keyClick(view, Qt.Key_Down) + qtbot.wait(200) + dialog.accept() + qtbot.wait(500) assert numpy.sum(expected_df[0].as_matrix() == dialog.get_value().as_matrix()) == len(expected_df) @@ -383,23 +385,24 @@ def test_dataframeeditor_edit_complex(qtbot, monkeypatch): qtbot.waitForWindowShown(dialog) view = dialog.dataTable - qtbot.keyPress(view, Qt.Key_Right) - qtbot.keyPress(view, Qt.Key_Down) - qtbot.keyPress(view, Qt.Key_Space) - qtbot.keyPress(view.focusWidget(), Qt.Key_Backspace) + qtbot.keyClick(view, Qt.Key_Right) + qtbot.keyClick(view, Qt.Key_Down) + qtbot.keyClick(view, Qt.Key_Space) + qtbot.keyClick(view.focusWidget(), Qt.Key_Backspace) qtbot.keyClicks(view.focusWidget(), "42") - qtbot.keyPress(view.focusWidget(), Qt.Key_Down) + qtbot.keyClick(view.focusWidget(), Qt.Key_Down) MockQMessageBox.critical.assert_called_with(ANY, "Error", ANY) assert MockQMessageBox.critical.call_count == count * 2 - 1 - qtbot.keyPress(view, Qt.Key_Down) + qtbot.keyClick(view, Qt.Key_Down) qtbot.keyClick(view, '1') - qtbot.keyPress(view.focusWidget(), Qt.Key_Down) + qtbot.keyClick(view.focusWidget(), Qt.Key_Down) MockQMessageBox.critical.assert_called_with( ANY, "Error", ("Editing dtype {0!s} not yet supported." .format(type(test_df.iloc[1, 0]).__name__))) assert MockQMessageBox.critical.call_count == count * 2 - qtbot.keyPress(view, Qt.Key_Return) - qtbot.wait(1000) + qtbot.wait(200) + dialog.accept() + qtbot.wait(500) assert numpy.sum(test_df[0].as_matrix() == dialog.get_value().as_matrix()) == len(test_df) @@ -448,13 +451,14 @@ def test_dataframeeditor_edit_bool(qtbot, monkeypatch): qtbot.keyPress(view, Qt.Key_Right) for test_str in test_strs: - qtbot.keyPress(view, Qt.Key_Space) - qtbot.keyPress(view.focusWidget(), Qt.Key_Backspace) + qtbot.keyClick(view, Qt.Key_Space) + qtbot.keyClick(view.focusWidget(), Qt.Key_Backspace) qtbot.keyClicks(view.focusWidget(), test_str) - qtbot.keyPress(view.focusWidget(), Qt.Key_Down) + qtbot.keyClick(view.focusWidget(), Qt.Key_Down) assert not MockQMessageBox.critical.called - qtbot.keyPress(view, Qt.Key_Return) - qtbot.wait(1000) + qtbot.wait(200) + dialog.accept() + qtbot.wait(500) assert (numpy.sum(expected_df[0].as_matrix() == dialog.get_value().as_matrix()[:, 0]) == len(expected_df)) From bc77221e382b6e4c7056dd594f840e0877046890 Mon Sep 17 00:00:00 2001 From: "C.A.M. Gerlach" Date: Sat, 10 Mar 2018 15:36:29 -0600 Subject: [PATCH 3/3] Add standard headers and improve docstrings of affected tests --- spyder/app/tests/test_mainwindow.py | 5 +- spyder/plugins/tests/test_ipythonconsole.py | 31 +++++++---- .../tests/test_arrayeditor.py | 38 +++++++++---- .../tests/test_dataframeeditor.py | 53 ++++++++++++++----- 4 files changed, 90 insertions(+), 37 deletions(-) diff --git a/spyder/app/tests/test_mainwindow.py b/spyder/app/tests/test_mainwindow.py index f961fc50f81..beeef9b970e 100644 --- a/spyder/app/tests/test_mainwindow.py +++ b/spyder/app/tests/test_mainwindow.py @@ -7,7 +7,7 @@ # ----------------------------------------------------------------------------- """ -Tests for the main window +Tests for the main window. """ # Standard library imports @@ -216,8 +216,7 @@ def test_calltip(main_window, qtbot): @pytest.mark.use_introspection def test_get_help(main_window, qtbot): """ - Test that Help is working when called from the Editor and the - IPython console. + Test that Help works when called from the Editor and the IPython console. """ shell = main_window.ipyconsole.get_current_shellwidget() control = shell._control diff --git a/spyder/plugins/tests/test_ipythonconsole.py b/spyder/plugins/tests/test_ipythonconsole.py index 362e3b357c6..ccfeabc773e 100644 --- a/spyder/plugins/tests/test_ipythonconsole.py +++ b/spyder/plugins/tests/test_ipythonconsole.py @@ -1,9 +1,16 @@ # -*- coding: utf-8 -*- -# +# ----------------------------------------------------------------------------- # Copyright © Spyder Project Contributors -# Licensed under the terms of the MIT License # +# Licensed under the terms of the MIT License +# (see spyder/__init__.py for details) +# ----------------------------------------------------------------------------- + +""" +Tests for the IPython console plugin. +""" +# Standard library imports import codecs import os import os.path as osp @@ -11,6 +18,7 @@ import tempfile from textwrap import dedent +# Third party imports import cloudpickle from flaky import flaky import ipykernel @@ -20,6 +28,7 @@ from qtpy.QtCore import Qt import zmq +# Local imports from spyder.config.gui import get_color_scheme from spyder.config.main import CONF from spyder.py3compat import PY2, to_text_string @@ -28,17 +37,17 @@ from spyder.utils.programs import TEMPDIR -#============================================================================== +# ============================================================================= # Constants -#============================================================================== +# ============================================================================= SHELL_TIMEOUT = 20000 TEMP_DIRECTORY = tempfile.gettempdir() NON_ASCII_DIR = osp.join(TEMP_DIRECTORY, u'測試', u'اختبار') -#============================================================================== +# ============================================================================= # Utillity Functions -#============================================================================== +# ============================================================================= def get_console_font_color(syntax_style): styles = create_style_class(syntax_style).styles font_color = styles[Name] @@ -51,9 +60,9 @@ def get_console_background_color(style_sheet): return background_color -#============================================================================== +# ============================================================================= # Qt Test Fixtures -#============================================================================== +# ============================================================================= @pytest.fixture def ipyconsole(qtbot, request): """IPython console fixture.""" @@ -97,9 +106,9 @@ def close_console(): return console -#============================================================================== +# ============================================================================= # Tests -#============================================================================== +# ============================================================================= @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.auto_backend @@ -824,7 +833,7 @@ def test_sys_argv_clear(ipyconsole, qtbot): @pytest.mark.slow @flaky(max_runs=3) def test_set_elapsed_time(ipyconsole, qtbot): - """Test timer.""" + """Test that the IPython console elapsed timer is set correctly.""" shell = ipyconsole.get_current_shellwidget() client = ipyconsole.get_current_client() qtbot.waitUntil(lambda: shell._prompt_html is not None, diff --git a/spyder/widgets/variableexplorer/tests/test_arrayeditor.py b/spyder/widgets/variableexplorer/tests/test_arrayeditor.py index 37d9cecc80f..d97a39dd9db 100644 --- a/spyder/widgets/variableexplorer/tests/test_arrayeditor.py +++ b/spyder/widgets/variableexplorer/tests/test_arrayeditor.py @@ -1,10 +1,13 @@ # -*- coding: utf-8 -*- -# +# ----------------------------------------------------------------------------- # Copyright © Spyder Project Contributors +# # Licensed under the terms of the MIT License +# (see spyder/__init__.py for details) +# ----------------------------------------------------------------------------- """ -Tests for arrayeditor.py +Tests for the array editor. """ # Standard library imports @@ -26,28 +29,35 @@ from spyder.widgets.variableexplorer.arrayeditor import ArrayEditor, ArrayModel +# ============================================================================= +# Utility functions +# ============================================================================= def launch_arrayeditor(data, title="", xlabels=None, ylabels=None): - """Helper routine to launch an arrayeditor and return its result""" + """Helper routine to launch an arrayeditor and return its result.""" dlg = ArrayEditor() assert dlg.setup_and_check(data, title, xlabels=xlabels, ylabels=ylabels) dlg.show() dlg.accept() # trigger slot connected to OK button return dlg.get_value() + def setup_arrayeditor(qbot, data, title="", xlabels=None, ylabels=None): """Setups an arrayeditor.""" dlg = ArrayEditor() - dlg.setup_and_check(data, title, xlabels=xlabels, ylabels=ylabels) + dlg.setup_and_check(data, title, xlabels=xlabels, ylabels=ylabels) dlg.show() qbot.addWidget(dlg) return dlg -# --- Tests -# ----------------------------------------------------------------------------- + +# ============================================================================= +# Tests +# ============================================================================= def test_type_errors(qtbot): - """Verify that we don't get a TypeError for certain structured arrays. + """ + Verify that we don't get a TypeError for certain structured arrays. - Fixes issue 5254. + Fixes issue #5254. """ arr = np.ones(2, dtype=[('X', 'f8', (2,10)), ('S', 'S10')]) dlg = setup_arrayeditor(qtbot, arr) @@ -186,7 +196,11 @@ def test_arrayeditor_edit_2d_array(qtbot): def test_arraymodel_set_data_overflow(monkeypatch): - """Unit test #6114: entry of an overflow int caught and handled properly""" + """ + Test that entry of an overflowing integer is caught and handled properly. + + Unit regression test for #6114 . + """ MockQMessageBox = Mock() attr_to_patch = 'spyder.widgets.variableexplorer.arrayeditor.QMessageBox' monkeypatch.setattr(attr_to_patch, MockQMessageBox) @@ -210,7 +224,11 @@ def test_arraymodel_set_data_overflow(monkeypatch): @flaky(max_runs=3) def test_arrayeditor_edit_overflow(qtbot, monkeypatch): - """Int. test #6114: entry of an overflow int caught and handled properly""" + """ + Test that entry of an overflowing integer is caught and handled properly. + + Integration regression test for #6114 . + """ MockQMessageBox = Mock() attr_to_patch = 'spyder.widgets.variableexplorer.arrayeditor.QMessageBox' monkeypatch.setattr(attr_to_patch, MockQMessageBox) diff --git a/spyder/widgets/variableexplorer/tests/test_dataframeeditor.py b/spyder/widgets/variableexplorer/tests/test_dataframeeditor.py index 45d98c483da..c298e6c9026 100644 --- a/spyder/widgets/variableexplorer/tests/test_dataframeeditor.py +++ b/spyder/widgets/variableexplorer/tests/test_dataframeeditor.py @@ -1,22 +1,25 @@ # -*- coding: utf-8 -*- -# +# ----------------------------------------------------------------------------- # Copyright © Spyder Project Contributors +# # Licensed under the terms of the MIT License +# (see spyder/__init__.py for details) +# ----------------------------------------------------------------------------- """ -Tests for dataframeeditor.py +Tests for the dataframe editor. """ from __future__ import division # Standard library imports +import os from sys import platform from datetime import datetime try: from unittest.mock import Mock, ANY except ImportError: from mock import Mock, ANY # Python 2 -import os # Third party imports from pandas import DataFrame, date_range, read_csv, concat @@ -35,9 +38,16 @@ DataFrameEditor, DataFrameModel) from spyder.py3compat import PY2 + +# ============================================================================= +# Constants +# ============================================================================= FILES_PATH = os.path.dirname(os.path.realpath(__file__)) -# Helper functions + +# ============================================================================= +# Utility functions +# ============================================================================= def colorclose(color, hsva_expected): """ Compares HSV values which are stored as 16-bit integers. @@ -51,9 +61,10 @@ def data(dfm, i, j): def bgcolor(dfm, i, j): return dfm.get_bgcolor(dfm.createIndex(i, j)) -# --- Tests -# ----------------------------------------------------------------------------- +# ============================================================================= +# Tests +# ============================================================================= def test_dataframemodel_basic(): df = DataFrame({'colA': [1, 3], 'colB': ['c', 'a']}) dfm = DataFrameModel(df) @@ -166,7 +177,7 @@ def test_dataframemodel_with_format_percent_d_and_nan(): """ Test DataFrameModel with format `%d` and dataframe containing NaN - Regression test for issue 4139. + Regression test for issue #4139. """ np_array = numpy.zeros(2) np_array[1] = numpy.nan @@ -275,7 +286,11 @@ def test_sort_dataframe_with_category_dtypes(qtbot): # cf. issue 5361 def test_dataframemodel_set_data_overflow(monkeypatch): - """Test for #6114: Overflowing ints are caught and handled properly""" + """ + Test that entry of an overflowing integer is caught and handled properly. + + Unit regression test for issue #6114 . + """ MockQMessageBox = Mock() attr_to_patch = ('spyder.widgets.variableexplorer' + '.dataframeeditor.QMessageBox') @@ -303,7 +318,11 @@ def test_dataframemodel_set_data_overflow(monkeypatch): @flaky(max_runs=3) @pytest.mark.no_xvfb def test_dataframeeditor_edit_overflow(qtbot, monkeypatch): - """Test #6114: Entry of an overflow int is caught and handled properly""" + """ + Test that entry of an overflowing integer is caught and handled properly. + + Integration regression test for issue #6114 . + """ MockQMessageBox = Mock() attr_to_patch = ('spyder.widgets.variableexplorer' + '.dataframeeditor.QMessageBox') @@ -347,7 +366,11 @@ def test_dataframeeditor_edit_overflow(qtbot, monkeypatch): def test_dataframemodel_set_data_complex(monkeypatch): - """Test for #6115: Editing complex dtypes raises error in df editor""" + """ + Test that editing complex dtypes is handled gracefully in df editor. + + Unit regression test for issue #6115 . + """ MockQMessageBox = Mock() attr_to_patch = ('spyder.widgets.variableexplorer' + '.dataframeeditor.QMessageBox') @@ -369,7 +392,11 @@ def test_dataframemodel_set_data_complex(monkeypatch): @flaky(max_runs=3) @pytest.mark.no_xvfb def test_dataframeeditor_edit_complex(qtbot, monkeypatch): - """Test for #6115: editing complex dtypes raises error in df editor""" + """ + Test that editing complex dtypes is handled gracefully in df editor. + + Integration regression test for issue #6115 . + """ MockQMessageBox = Mock() attr_to_patch = ('spyder.widgets.variableexplorer' + '.dataframeeditor.QMessageBox') @@ -408,7 +435,7 @@ def test_dataframeeditor_edit_complex(qtbot, monkeypatch): def test_dataframemodel_set_data_bool(monkeypatch): - """Test that bools are editible in df and false-y strs are detected""" + """Test that bools are editible in df and false-y strs are detected.""" MockQMessageBox = Mock() attr_to_patch = ('spyder.widgets.variableexplorer' + '.dataframeeditor.QMessageBox') @@ -431,7 +458,7 @@ def test_dataframemodel_set_data_bool(monkeypatch): @flaky(max_runs=3) @pytest.mark.no_xvfb def test_dataframeeditor_edit_bool(qtbot, monkeypatch): - """Test that bools are editible in df and false-y strs are detected""" + """Test that bools are editible in df and false-y strs are detected.""" MockQMessageBox = Mock() attr_to_patch = ('spyder.widgets.variableexplorer' + '.dataframeeditor.QMessageBox')