Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR: Add more tests for the main window #4110

Merged
merged 8 commits into from
Feb 10, 2017
2 changes: 1 addition & 1 deletion continuous_integration/appveyor/install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ function DownloadMiniconda ($python_version, $platform_suffix) {
if ($python_version -match "3.5") {
$filename = "Miniconda3-latest-Windows-" + $platform_suffix + ".exe"
} else {
$filename = "Miniconda-latest-Windows-" + $platform_suffix + ".exe"
$filename = "Miniconda2-latest-Windows-" + $platform_suffix + ".exe"
}
$url = $MINICONDA_URL + $filename

Expand Down
4 changes: 2 additions & 2 deletions spyder/app/mainwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@
#==============================================================================
# Create splash screen out of MainWindow to reduce perceived startup time.
#==============================================================================
from spyder.config.base import _, get_image_path, DEV
from spyder.config.base import _, get_image_path, DEV, PYTEST
SPLASH = QSplashScreen(QPixmap(get_image_path('splash.svg'), 'svg'))
SPLASH_FONT = SPLASH.font()
SPLASH_FONT.setPixelSize(10)
Expand Down Expand Up @@ -2922,7 +2922,7 @@ def run_spyder(app, options, args):
# the window
app.focusChanged.connect(main.change_last_focused_widget)

if not os.environ.get('SPYDER_PYTEST', None):
if not PYTEST:
app.exec_()
return main

Expand Down
10 changes: 10 additions & 0 deletions spyder/app/tests/script.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#%%
a = 10


#%%
li = [1, 2, 3]

#%%
import numpy as np
arr = np.array(li)
169 changes: 162 additions & 7 deletions spyder/app/tests/test_mainwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,52 @@
Tests for the main window
"""

import os
import os.path as osp

import numpy as np
from numpy.testing import assert_array_equal
import pytest
from qtpy.QtCore import Qt
from qtpy.QtCore import Qt, QTimer
from qtpy.QtTest import QTest
from qtpy.QtWidgets import QApplication, QFileDialog, QLineEdit

from spyder.app.cli_options import get_options
from spyder.app.mainwindow import initialize, run_spyder


#==============================================================================
# Constants
#==============================================================================
LOCATION = osp.realpath(osp.join(os.getcwd(), osp.dirname(__file__)))


#==============================================================================
# Utility functions
#==============================================================================
def open_file_in_editor(main_window, fname, directory=None):
"""Open a file using the Editor and its open file dialog"""
top_level_widgets = QApplication.topLevelWidgets()
for w in top_level_widgets:
if isinstance(w, QFileDialog):
if directory is not None:
w.setDirectory(directory)
input_field = w.findChildren(QLineEdit)[0]
input_field.setText(fname)
QTest.keyClick(w, Qt.Key_Enter)


def reset_run_code(qtbot, shell, code_editor, nsb):
"""Reset state after a run code test"""
shell.execute('%reset -f')
qtbot.waitUntil(lambda: nsb.editor.model.rowCount() == 0, timeout=1500)
code_editor.setFocus()
qtbot.keyClick(code_editor, Qt.Key_Home, modifier=Qt.ControlModifier)


#==============================================================================
# Fixtures
#==============================================================================
@pytest.fixture
def main_window():
app = initialize()
Expand All @@ -23,11 +62,125 @@ def main_window():
return widget


#==============================================================================
# Tests
#==============================================================================
def test_run_code(main_window, qtbot):
"""Test all the different ways we have to run code"""
# ---- Setup ----
# Wait until the window is fully up
shell = main_window.ipyconsole.get_current_shellwidget()
qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=15000)

# Load test file
main_window.editor.load(osp.join(LOCATION, 'script.py'))

# Move to the editor's first line
code_editor = main_window.editor.get_focus_widget()
code_editor.setFocus()
qtbot.keyClick(code_editor, Qt.Key_Home, modifier=Qt.ControlModifier)

# Get a reference to the namespace browser widget
nsb = main_window.variableexplorer.get_focus_widget()

# ---- Run file ----
qtbot.keyClick(code_editor, Qt.Key_F5)

# Wait until all objects have appeared in the variable explorer
qtbot.waitUntil(lambda: nsb.editor.model.rowCount() == 3, timeout=1500)

# Verify result
assert shell.get_value('a') == 10
assert shell.get_value('li') == [1, 2, 3]
assert_array_equal(shell.get_value('arr'), np.array([1, 2, 3]))

reset_run_code(qtbot, shell, code_editor, nsb)

# ---- Run lines ----
# Run the whole file line by line
for _ in range(code_editor.blockCount()):
qtbot.keyClick(code_editor, Qt.Key_F9)
qtbot.wait(100)

# Wait until all objects have appeared in the variable explorer
qtbot.waitUntil(lambda: nsb.editor.model.rowCount() == 3, timeout=1500)

# Verify result
assert shell.get_value('a') == 10
assert shell.get_value('li') == [1, 2, 3]
assert_array_equal(shell.get_value('arr'), np.array([1, 2, 3]))

reset_run_code(qtbot, shell, code_editor, nsb)

# ---- Run cell and advance ----
# Run the three cells present in file
for _ in range(3):
qtbot.keyClick(code_editor, Qt.Key_Return, modifier=Qt.ShiftModifier)
qtbot.wait(100)

# Wait until all objects have appeared in the variable explorer
qtbot.waitUntil(lambda: nsb.editor.model.rowCount() == 3, timeout=1500)

# Verify result
assert shell.get_value('a') == 10
assert shell.get_value('li') == [1, 2, 3]
assert_array_equal(shell.get_value('arr'), np.array([1, 2, 3]))

reset_run_code(qtbot, shell, code_editor, nsb)

# ---- Run cell ----
# Run the first cell in file
qtbot.keyClick(code_editor, Qt.Key_Return, modifier=Qt.ControlModifier)

# Wait until the object has appeared in the variable explorer
qtbot.waitUntil(lambda: nsb.editor.model.rowCount() == 1, timeout=1500)

# Verify result
assert shell.get_value('a') == 10

# Press Ctrl+Enter a second time to verify that we're *not* advancing
# to the next cell
qtbot.keyClick(code_editor, Qt.Key_Return, modifier=Qt.ControlModifier)
assert nsb.editor.model.rowCount() == 1

main_window.close()


@pytest.mark.skipif(os.name == 'nt', reason="It's timing out sometimes on Windows")
def test_open_files_in_new_editor_window(main_window, qtbot):
"""
This tests that opening files in a new editor window
is working as expected.

Test for issue 4085
"""
# Wait until the window is fully up
shell = main_window.ipyconsole.get_current_shellwidget()
qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=15000)

# Set a timer to manipulate the open dialog while it's running
QTimer.singleShot(2000, lambda: open_file_in_editor(main_window,
'script.py',
directory=LOCATION))

# Create a new editor window
# Note: editor.load() uses the current editorstack by default
main_window.editor.create_new_window()
main_window.editor.load()

# Perform the test
# Note: There's always one file open in the Editor
editorstack = main_window.editor.get_current_editorstack()
assert editorstack.get_stack_count() == 2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test fails when there are previous files open in Spyder (in a previous session)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's meant to be run in CIs. We could skip it if we're not running it not in a CI.


main_window.close()


def test_maximize_minimize_plugins(main_window, qtbot):
"""Test that the maximize button is working correctly."""
# Wait until the window is fully up
shell = main_window.ipyconsole.get_current_shellwidget()
qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=6000)
qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=15000)

# Set focus to the Editor
main_window.editor.get_focus_widget().setFocus()
Expand All @@ -44,6 +197,8 @@ def test_maximize_minimize_plugins(main_window, qtbot):
qtbot.mouseClick(max_button, Qt.LeftButton)
assert not main_window.editor.ismaximized

main_window.close()


def test_issue_4066(main_window, qtbot):
"""
Expand All @@ -56,12 +211,12 @@ def test_issue_4066(main_window, qtbot):
"""
# Create the object
shell = main_window.ipyconsole.get_current_shellwidget()
qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=6000)
qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=15000)
shell.execute('myobj = [1, 2, 3]')

# Open editor associated with that object and get a reference to it
nsb = main_window.variableexplorer.get_focus_widget()
qtbot.waitUntil(lambda: nsb.editor.model.rowCount() > 0, timeout=500)
qtbot.waitUntil(lambda: nsb.editor.model.rowCount() > 0, timeout=1500)
nsb.editor.setFocus()
nsb.editor.edit_item()
obj_editor_id = list(nsb.editor.delegate._editors.keys())[0]
Expand All @@ -70,7 +225,7 @@ def test_issue_4066(main_window, qtbot):
# Move to the IPython console and delete that object
main_window.ipyconsole.get_focus_widget().setFocus()
shell.execute('del myobj')
qtbot.waitUntil(lambda: nsb.editor.model.rowCount() == 0, timeout=500)
qtbot.waitUntil(lambda: nsb.editor.model.rowCount() == 0, timeout=1500)

# Close editor
ok_widget = obj_editor.bbox.button(obj_editor.bbox.Ok)
Expand All @@ -88,13 +243,13 @@ def test_varexp_edit_inline(main_window, qtbot):
"""
# Create object
shell = main_window.ipyconsole.get_current_shellwidget()
qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=6000)
qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=15000)
shell.execute('a = 10')

# Edit object
main_window.variableexplorer.visibility_changed(True)
nsb = main_window.variableexplorer.get_focus_widget()
qtbot.waitUntil(lambda: nsb.editor.model.rowCount() > 0, timeout=500)
qtbot.waitUntil(lambda: nsb.editor.model.rowCount() > 0, timeout=1500)
nsb.editor.setFocus()
nsb.editor.edit_item()

Expand Down
5 changes: 5 additions & 0 deletions spyder/config/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@
TEST = os.environ.get('SPYDER_TEST')


# To do some adjustments for pytest
# This env var is defined in runtests.py
PYTEST = os.environ.get('SPYDER_PYTEST')


#==============================================================================
# Debug helpers
#==============================================================================
Expand Down
22 changes: 15 additions & 7 deletions spyder/plugins/editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
QToolBar, QVBoxLayout, QWidget)

# Local imports
from spyder.config.base import _, get_conf_path
from spyder.config.base import _, get_conf_path, PYTEST
from spyder.config.main import (CONF, RUN_CELL_SHORTCUT,
RUN_CELL_AND_ADVANCE_SHORTCUT)
from spyder.config.utils import (get_edit_filetypes, get_edit_filters,
Expand Down Expand Up @@ -1813,11 +1813,19 @@ def load(self, filenames=None, goto=None, word='', editorwindow=None,
osp.splitext(filename0)[1])
else:
selectedfilter = ''
filenames, _sf = getopenfilenames(parent_widget,
_("Open file"), basedir,
self.edit_filters,
selectedfilter=selectedfilter,
options=QFileDialog.HideNameFilterDetails)
if not PYTEST:
filenames, _sf = getopenfilenames(
parent_widget,
_("Open file"), basedir,
self.edit_filters,
selectedfilter=selectedfilter,
options=QFileDialog.HideNameFilterDetails)
else:
# Use a Qt (i.e. scriptable) dialog for pytest
dialog = QFileDialog(parent_widget, _("Open file"),
options=QFileDialog.DontUseNativeDialog)
if dialog.exec_():
filenames = dialog.selectedFiles()
self.redirect_stdio.emit(True)
if filenames:
filenames = [osp.normpath(fname) for fname in filenames]
Expand Down Expand Up @@ -2311,7 +2319,7 @@ def run_file(self, debug=False):
if self.dialog_size is not None:
dialog.resize(self.dialog_size)
dialog.setup(fname)
if CONF.get('run', 'open_at_least_once', True):
if CONF.get('run', 'open_at_least_once', not PYTEST):
# Open Run Config dialog at least once: the first time
# a script is ever run in Spyder, so that the user may
# see it at least once and be conscious that it exists
Expand Down