1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
|
# -*- coding: utf-8 -*-
#
# Copyright © Spyder Project Contributors
# Licensed under the terms of the MIT License
# (see LICENSE.txt for details)
"""
Tests for the integration of the plugin with Spyder.
"""
# Standard library imports
from collections import OrderedDict
import os
import time
# Third party imports
from qtpy.QtCore import Qt
from qtpy.QtWidgets import QApplication
# Spyder imports
from spyder import version_info as spyder_version_info
from spyder.api.plugins import Plugins
from spyder.config.base import running_in_ci
from spyder.plugins.mainmenu.api import ApplicationMenus
# Local imports
from spyder_unittest.unittestplugin import UnitTestPlugin
from spyder_unittest.widgets.configdialog import Config
def sleep_if_running_in_ci():
"""
Sleep if the tests are running in GitHub CI.
This prevents the error "QThread: Destroyed while thread is still running"
for some reason.
"""
if running_in_ci():
time.sleep(5)
QApplication.processEvents()
def test_menu_item(main_window):
"""
Test that plugin adds item 'Run unit tests' to Run menu.
"""
main_menu = main_window.get_plugin(Plugins.MainMenu)
run_menu = main_menu.get_application_menu(ApplicationMenus.Run)
actions = run_menu.get_actions()
# Filter out seperators (indicated by action is None) and convert to text
menu_items = [action.text() for action in actions if action]
assert 'Run unit tests' in menu_items
def test_pythonpath_change(main_window):
"""
Test that pythonpath changes in Spyder propagate to UnitTestWidget.
"""
ppm = main_window.get_plugin(Plugins.PythonpathManager)
unittest_plugin = main_window.get_plugin(UnitTestPlugin.NAME)
new_path = '/some/path'
new_path_dict = OrderedDict([(new_path, True)])
import importlib.metadata
if importlib.metadata.version('spyder').startswith('6.0.'):
ppm.get_container()._update_python_path(new_path_dict)
else:
# 6.1+
ppm.get_container()._save_paths(user_paths=new_path_dict)
assert unittest_plugin.get_widget().pythonpath == [new_path]
def test_default_working_dir(main_window, tmpdir):
"""
Test that plugin's default working dir is current working directory.
After creating a project, the plugin's default working dir should be the
same as the project directory. When the project is closed again, the
plugin's default working dir should revert back to the current working
directory.
"""
projects = main_window.get_plugin(Plugins.Projects)
unittest_plugin = main_window.get_plugin(UnitTestPlugin.NAME)
project_dir = str(tmpdir)
assert unittest_plugin.get_widget().default_wdir == os.getcwd()
sleep_if_running_in_ci()
projects.create_project(project_dir)
assert unittest_plugin.get_widget().default_wdir == project_dir
sleep_if_running_in_ci()
projects.close_project()
assert unittest_plugin.get_widget().default_wdir == os.getcwd()
def test_plugin_config(main_window, tmpdir, qtbot):
"""
Test that plugin uses the project's config file if a project is open.
"""
projects = main_window.get_plugin(Plugins.Projects)
unittest_plugin = main_window.get_plugin(UnitTestPlugin.NAME)
unittest_widget = unittest_plugin.get_widget()
project_dir = str(tmpdir)
config_file_path = tmpdir.join('.spyproject', 'config', 'unittest.ini')
# Test config file does not exist and config is empty
assert not config_file_path.check()
assert unittest_widget.config is None
# Create new project
sleep_if_running_in_ci()
projects.create_project(project_dir)
# Test config file does exist but config is empty
assert config_file_path.check()
assert 'framework = ' in config_file_path.read().splitlines()
assert unittest_widget.config is None
# Set config and test that this is recorded in config file
config = Config(framework='unittest', wdir=str(tmpdir))
with qtbot.waitSignal(unittest_widget.sig_newconfig):
unittest_widget.config = config
assert 'framework = unittest' in config_file_path.read().splitlines()
# Close project and test that config is empty
sleep_if_running_in_ci()
projects.close_project()
assert unittest_widget.config is None
# Re-open project and test that config is correctly read
sleep_if_running_in_ci()
projects.open_project(project_dir)
assert unittest_widget.config == config
# Close project before ending test, which removes the project dir
sleep_if_running_in_ci()
projects.close_project()
def test_go_to_test_definition(main_window, tmpdir, qtbot):
"""
Test that double clicking on a test result opens the file with the test
definition in the editor with the cursor on the test definition.
"""
unittest_plugin = main_window.get_plugin(UnitTestPlugin.NAME)
unittest_widget = unittest_plugin.get_widget()
model = unittest_widget.testdatamodel
view = unittest_widget.testdataview
# Write test file
testdir_str = str(tmpdir)
testfile_str = tmpdir.join('test_foo.py').strpath
os.chdir(testdir_str)
with open(testfile_str, 'w') as f:
f.write("def test_ok(): assert 1+1 == 2\n"
"def test_fail(): assert 1+1 == 3\n")
# Run tests
config = Config(wdir=testdir_str, framework='pytest', coverage=False)
with qtbot.waitSignal(
unittest_widget.sig_finished, timeout=10000, raising=True):
unittest_widget.run_tests(config)
# Check that row 1 corresponds to `test_fail`
index = model.index(1, 1)
point = view.visualRect(index).center()
assert view.indexAt(point).data(Qt.DisplayRole).endswith('test_fail')
# Double click on `test_fail`
unittest_plugin.switch_to_plugin()
with qtbot.waitSignal(view.sig_edit_goto):
qtbot.mouseClick(view.viewport(), Qt.LeftButton, pos=point, delay=100)
qtbot.mouseDClick(view.viewport(), Qt.LeftButton, pos=point)
# Check that test file is opened in editor
editor = main_window.get_plugin(Plugins.Editor)
filename = editor.get_current_filename()
assert filename == testfile_str
# Check that cursor is on line defining `test_fail`
cursor = editor.get_current_editor().textCursor()
line = cursor.block().text()
assert line.startswith('def test_fail')
|