File: test_unittestplugin.py

package info (click to toggle)
spyder-unittest 0.7.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 676 kB
  • sloc: python: 3,477; sh: 9; makefile: 4
file content (186 lines) | stat: -rw-r--r-- 6,370 bytes parent folder | download
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')