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

Fix test_pytestrunner_start #150

Merged
merged 4 commits into from
May 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 9 additions & 12 deletions spyder_unittest/backend/runnerbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from qtpy.QtCore import (QObject, QProcess, QProcessEnvironment, QTextCodec,
Signal)
from spyder.py3compat import to_text_string
from spyder.utils.misc import add_pathlist_to_PYTHONPATH, get_python_executable
from spyder.utils.misc import get_python_executable

try:
from importlib.util import find_spec as find_spec_or_loader
Expand Down Expand Up @@ -179,17 +179,14 @@ def _prepare_process(self, config, pythonpath):
process.setProcessChannelMode(QProcess.MergedChannels)
process.setWorkingDirectory(config.wdir)
process.finished.connect(self.finished)
if pythonpath is not None:
env = [
to_text_string(_pth)
for _pth in process.systemEnvironment()
]
add_pathlist_to_PYTHONPATH(env, pythonpath)
processEnvironment = QProcessEnvironment()
for envItem in env:
envName, separator, envValue = envItem.partition('=')
processEnvironment.insert(envName, envValue)
process.setProcessEnvironment(processEnvironment)
if pythonpath:
env = QProcessEnvironment.systemEnvironment()
old_python_path = env.value('PYTHONPATH', None)
python_path_str = os.pathsep.join(pythonpath)
if old_python_path:
python_path_str += os.pathsep + old_python_path
env.insert('PYTHONPATH', python_path_str)
process.setProcessEnvironment(env)
return process

def start(self, config, pythonpath):
Expand Down
56 changes: 24 additions & 32 deletions spyder_unittest/backend/tests/test_pytestrunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

# Third party imports
from qtpy.QtCore import QByteArray
from spyder.utils.misc import get_python_executable

# Local imports
from spyder_unittest.backend.pytestrunner import (PyTestRunner,
Expand All @@ -28,50 +27,43 @@
def test_pytestrunner_is_installed():
assert PyTestRunner(None).is_installed()

def test_pytestrunner_start(monkeypatch):
MockQProcess = Mock()
monkeypatch.setattr('spyder_unittest.backend.runnerbase.QProcess',
MockQProcess)
mock_process = MockQProcess()
mock_process.systemEnvironment = lambda: ['VAR=VALUE', 'PYTHONPATH=old']

MockEnvironment = Mock()
monkeypatch.setattr(
'spyder_unittest.backend.runnerbase.QProcessEnvironment',
MockEnvironment)
mock_environment = MockEnvironment()

mock_remove = Mock(side_effect=OSError())
monkeypatch.setattr('spyder_unittest.backend.runnerbase.os.remove',
mock_remove)

def test_pytestrunner_create_argument_list(monkeypatch):
MockZMQStreamReader = Mock()
monkeypatch.setattr(
'spyder_unittest.backend.pytestrunner.ZmqStreamReader',
MockZMQStreamReader)
mock_reader = MockZMQStreamReader()
mock_reader.port = 42

runner = PyTestRunner(None, 'results')
config = Config('pytest', 'wdir')
runner.start(config, ['pythondir'])
runner.reader = mock_reader
monkeypatch.setattr('spyder_unittest.backend.pytestrunner.os.path.dirname',
lambda _: 'dir')
pyfile, port = runner.create_argument_list()
assert pyfile == 'dir{}pytestworker.py'.format(os.sep)
assert port == '42'

mock_process.setWorkingDirectory.assert_called_once_with('wdir')
mock_process.finished.connect.assert_called_once_with(runner.finished)
mock_process.setProcessEnvironment.assert_called_once_with(
mock_environment)

workerfile = os.path.abspath(
os.path.join(os.path.dirname(__file__), os.pardir, 'pytestworker.py'))
mock_process.start.assert_called_once_with(
get_python_executable(), [workerfile, '42'])
def test_pytestrunner_start(monkeypatch):
MockZMQStreamReader = Mock()
monkeypatch.setattr(
'spyder_unittest.backend.pytestrunner.ZmqStreamReader',
MockZMQStreamReader)
mock_reader = MockZMQStreamReader()

mock_environment.insert.assert_any_call('VAR', 'VALUE')
# mock_environment.insert.assert_any_call('PYTHONPATH', 'pythondir:old')
# TODO: Find out why above test fails
mock_remove.called_once_with('results')
MockRunnerBase = Mock(name='RunnerBase')
monkeypatch.setattr('spyder_unittest.backend.pytestrunner.RunnerBase',
MockRunnerBase)

runner = PyTestRunner(None, 'results')
config = Config()
runner.start(config, ['pythondir'])
assert runner.config is config
assert runner.reader is mock_reader
runner.reader.sig_received.connect.assert_called_once_with(
runner.process_output)
MockRunnerBase.start.assert_called_once_with(runner, config, ['pythondir'])


def test_pytestrunner_process_output_with_collected(qtbot):
runner = PyTestRunner(None)
Expand Down
76 changes: 76 additions & 0 deletions spyder_unittest/backend/tests/test_runnerbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,88 @@
# (see LICENSE.txt for details)
"""Tests for baserunner.py"""

# Standard library imports
import os

# Third party imports
import pytest

# Local imports
from spyder_unittest.backend.runnerbase import RunnerBase
from spyder_unittest.widgets.configdialog import Config

try:
from unittest.mock import Mock
except ImportError:
from mock import Mock # Python 2


def test_runnerbase_with_nonexisting_module():
class FooRunner(RunnerBase):
module = 'nonexisiting'

assert not FooRunner.is_installed()


@pytest.mark.parametrize('pythonpath,env_pythonpath', [
([], None),
(['pythonpath'], None),
(['pythonpath'], 'old')
])
def test_runnerbase_prepare_process(monkeypatch, pythonpath, env_pythonpath):
MockQProcess = Mock()
monkeypatch.setattr('spyder_unittest.backend.runnerbase.QProcess',
MockQProcess)
mock_process = MockQProcess()

MockEnvironment = Mock()
monkeypatch.setattr(
'spyder_unittest.backend.runnerbase.QProcessEnvironment.systemEnvironment',
MockEnvironment)
mock_environment = MockEnvironment()
mock_environment.configure_mock(**{'value.return_value': env_pythonpath})

config = Config('myRunner', 'wdir')
runner = RunnerBase(None, 'results')
runner._prepare_process(config, pythonpath)

mock_process.setWorkingDirectory.assert_called_once_with('wdir')
mock_process.finished.connect.assert_called_once_with(runner.finished)
if pythonpath:
if env_pythonpath:
mock_environment.insert.assert_any_call('PYTHONPATH',
'pythonpath{}{}'.format(
os.pathsep,
env_pythonpath))
else:
mock_environment.insert.assert_any_call('PYTHONPATH', 'pythonpath')
mock_process.setProcessEnvironment.assert_called_once()
else:
mock_environment.insert.assert_not_called()
mock_process.setProcessEnvironment.assert_not_called()


def test_runnerbase_start(monkeypatch):
MockQProcess = Mock()
monkeypatch.setattr('spyder_unittest.backend.runnerbase.QProcess',
MockQProcess)
mock_process = MockQProcess()

mock_remove = Mock(side_effect=OSError())
monkeypatch.setattr('spyder_unittest.backend.runnerbase.os.remove',
mock_remove)

monkeypatch.setattr(
'spyder_unittest.backend.runnerbase.get_python_executable',
lambda: 'python')

runner = RunnerBase(None, 'results')
runner._prepare_process = lambda c, p: mock_process
runner.create_argument_list = lambda: ['arg1', 'arg2']
config = Config('pytest', 'wdir')
mock_process.waitForStarted = lambda: False
with pytest.raises(RuntimeError):
runner.start(config, ['pythondir'])

mock_process.start.assert_called_once_with('python', ['arg1', 'arg2'])
mock_remove.assert_called_once_with('results')
2 changes: 1 addition & 1 deletion spyder_unittest/widgets/unittestgui.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ def test():

# add wdir's parent to python path, so that `import spyder_unittest` works
rootdir = osp.abspath(osp.join(wdir, osp.pardir))
widget.pythonpath = rootdir
widget.pythonpath = [rootdir]

widget.resize(800, 600)
widget.show()
Expand Down