Skip to content

Commit

Permalink
Merge pull request #182 from jitseniesen/target-env
Browse files Browse the repository at this point in the history
PR: Use target env instead of Spyder env when checking dependencies
  • Loading branch information
jitseniesen authored Aug 17, 2022
2 parents 7ed1349 + 876962e commit 94126d8
Show file tree
Hide file tree
Showing 20 changed files with 401 additions and 259 deletions.
14 changes: 0 additions & 14 deletions spyder_unittest/backend/noserunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,6 @@ class NoseRunner(RunnerBase):
module = 'nose'
name = 'nose'

def get_versions(self):
"""Return versions of framework and its plugins."""
import nose
from pkg_resources import iter_entry_points

versions = ['nose {}'.format(nose.__version__)]

for entry_point, _ in (nose.plugins.manager.EntryPointPluginManager
.entry_points):
for ep in iter_entry_points(entry_point):
versions.append(
" {} {}".format(ep.dist.project_name, ep.dist.version))
return versions

def create_argument_list(self, config, cov_path):
"""Create argument list for testing process."""
return [
Expand Down
25 changes: 3 additions & 22 deletions spyder_unittest/backend/pytestrunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from spyder.config.base import get_translation
from spyder_unittest.backend.runnerbase import (Category, RunnerBase,
TestResult, COV_TEST_NAME)
from spyder_unittest.backend.zmqstream import ZmqStreamReader
from spyder_unittest.backend.zmqreader import ZmqStreamReader

try:
_ = get_translation('spyder_unittest')
Expand All @@ -29,29 +29,10 @@ class PyTestRunner(RunnerBase):
module = 'pytest'
name = 'pytest'

def get_versions(self):
"""Return versions of framework and its plugins."""
import pytest
versions = ['pytest {}'.format(pytest.__version__)]

class GetPluginVersionsPlugin():
def pytest_cmdline_main(self, config):
nonlocal versions
plugininfo = config.pluginmanager.list_plugin_distinfo()
if plugininfo:
for plugin, dist in plugininfo:
versions.append(" {} {}".format(dist.project_name,
dist.version))

# --capture=sys needed on Windows to avoid
# ValueError: saved filedescriptor not valid anymore
pytest.main(['-V', '--capture=sys'],
plugins=[GetPluginVersionsPlugin()])
return versions

def create_argument_list(self, config, cov_path):
"""Create argument list for testing process."""
pyfile = os.path.join(os.path.dirname(__file__), 'pytestworker.py')
dirname = os.path.dirname(__file__)
pyfile = os.path.join(dirname, 'workers', 'pytestworker.py')
arguments = [pyfile, str(self.reader.port)]
if config.coverage:
arguments += [f'--cov={cov_path}', '--cov-report=term-missing']
Expand Down
29 changes: 0 additions & 29 deletions spyder_unittest/backend/runnerbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,35 +135,6 @@ def __init__(self, widget, resultfilename=None):
else:
self.resultfilename = resultfilename

@classmethod
def is_installed(cls):
"""
Check whether test framework is installed.
This function tests whether self.module is installed, but it does not
import it.
Returns
-------
bool
True if framework is installed, False otherwise.
"""
return find_spec_or_loader(cls.module) is not None

def get_versions(self):
"""
Return versions of framework and its installed plugins.
This function must only be called for installed frameworks.
Returns
-------
list of str
Strings with framework or plugin name, followed by
its version.
"""
raise NotImplementedError

def create_argument_list(self, config, cov_path):
"""
Create argument list for testing process (dummy).
Expand Down
24 changes: 0 additions & 24 deletions spyder_unittest/backend/tests/test_noserunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,27 +74,3 @@ def test_noserunner_load_data_passing_test_with_stdout(tmpdir):
results = runner.load_data()
assert results[0].extra_text == ['----- Captured stdout -----', 'stdout text']


def test_get_versions_without_plugins(monkeypatch):
import nose
import pkg_resources
monkeypatch.setattr(nose, '__version__', '1.2.3')
monkeypatch.setattr(pkg_resources, 'iter_entry_points', lambda x: ())
runner = NoseRunner(None)
assert runner.get_versions() == ['nose 1.2.3']


def test_get_versions_with_plugins(monkeypatch):
import nose
import pkg_resources
monkeypatch.setattr(nose, '__version__', '1.2.3')
dist = pkg_resources.Distribution(project_name='myPlugin',
version='4.5.6')
ep = pkg_resources.EntryPoint('name', 'module_name', dist=dist)
monkeypatch.setattr(pkg_resources,
'iter_entry_points',
lambda ept: (x for x in (ep,) if ept == nose.plugins
.manager.EntryPointPluginManager
.entry_points[0][0]))
runner = NoseRunner(None)
assert runner.get_versions() == ['nose 1.2.3', ' myPlugin 4.5.6']
35 changes: 1 addition & 34 deletions spyder_unittest/backend/tests/test_pytestrunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
"""Tests for pytestrunner.py"""

# Standard library imports
import os
import os.path as osp
import sys
from unittest.mock import Mock
Expand All @@ -22,10 +21,6 @@
from spyder_unittest.widgets.configdialog import Config


def test_pytestrunner_is_installed():
assert PyTestRunner(None).is_installed()


def test_pytestrunner_create_argument_list(monkeypatch):
config = Config()
cov_path = None
Expand All @@ -40,7 +35,7 @@ def test_pytestrunner_create_argument_list(monkeypatch):
monkeypatch.setattr('spyder_unittest.backend.pytestrunner.os.path.dirname',
lambda _: 'dir')
pyfile, port, *coverage = runner.create_argument_list(config, cov_path)
assert pyfile == 'dir{}pytestworker.py'.format(os.sep)
assert pyfile == osp.join('dir', 'workers', 'pytestworker.py')
assert port == '42'


Expand Down Expand Up @@ -273,31 +268,3 @@ def test_logreport_to_testresult_with_output(longrepr, prefix):
lineno=24)
assert logreport_to_testresult(report, 'ham') == expected


def test_get_versions_without_plugins(monkeypatch):
import pytest
monkeypatch.setattr(pytest, '__version__', '1.2.3')
from _pytest.config import PytestPluginManager
monkeypatch.setattr(
PytestPluginManager,
'list_plugin_distinfo', lambda _: ())

runner = PyTestRunner(None)
assert runner.get_versions() == ['pytest 1.2.3']


def test_get_versions_with_plugins(monkeypatch):
import pytest
import pkg_resources
monkeypatch.setattr(pytest, '__version__', '1.2.3')
dist1 = pkg_resources.Distribution(project_name='myPlugin1',
version='4.5.6')
dist2 = pkg_resources.Distribution(project_name='myPlugin2',
version='7.8.9')
from _pytest.config import PytestPluginManager
monkeypatch.setattr(
PytestPluginManager,
'list_plugin_distinfo', lambda _: (('1', dist1), ('2', dist2)))
runner = PyTestRunner(None)
assert runner.get_versions() == ['pytest 1.2.3', ' myPlugin1 4.5.6',
' myPlugin2 7.8.9']
5 changes: 0 additions & 5 deletions spyder_unittest/backend/tests/test_runnerbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,12 @@ def test_runnerbase_with_nonexisting_module():
class FooRunner(RunnerBase):
module = 'nonexisiting'

assert not FooRunner.is_installed()

foo_runner = FooRunner(None)
config = Config(foo_runner.module, 'wdir', True)

with pytest.raises(NotImplementedError):
foo_runner.create_argument_list(config, 'cov_path')

with pytest.raises(NotImplementedError):
foo_runner.get_versions()

with pytest.raises(NotImplementedError):
foo_runner.finished()

Expand Down
7 changes: 0 additions & 7 deletions spyder_unittest/backend/tests/test_unittestrunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,3 @@ def test_try_parse_header_starting_with_digit():
lines = ['0est_isupper (testfoo.TestStringMethods) ... ok']
res = runner.try_parse_result(lines, 0)
assert res is None


def test_get_versions(monkeypatch):
import platform
monkeypatch.setattr(platform, 'python_version', lambda: '1.2.3')
runner = UnittestRunner(None)
assert runner.get_versions() == ['unittest 1.2.3']
3 changes: 2 additions & 1 deletion spyder_unittest/backend/tests/test_zmqstream.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"""Tests for zmqstream.py"""

# Local imports
from spyder_unittest.backend.zmqstream import ZmqStreamReader, ZmqStreamWriter
from spyder_unittest.backend.zmqreader import ZmqStreamReader
from spyder_unittest.backend.workers.zmqwriter import ZmqStreamWriter


def test_zmqstream(qtbot):
Expand Down
9 changes: 0 additions & 9 deletions spyder_unittest/backend/unittestrunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,6 @@ class UnittestRunner(RunnerBase):
module = 'unittest'
name = 'unittest'

def get_versions(self):
"""
Return versions of framework and its plugins.
As 'unittest' is a built-in framework, we return the python version.
"""
import platform
return ['unittest {}'.format(platform.python_version())]

def create_argument_list(self, config, cov_path):
"""Create argument list for testing process."""
return ['-m', self.module, 'discover', '-v']
Expand Down
17 changes: 17 additions & 0 deletions spyder_unittest/backend/workers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# -*- coding: utf-8 -*-
#
# Copyright © Spyder Project Contributors
# Licensed under the terms of the MIT License
# (see LICENSE.txt for details)

"""
Code to be run in the target environment.
This directory contains scripts and supporting modules that are supposed
to be executed in the target environment (using the Python interpreter
that the user specifies in the Preferences) instead of the environment that
Spyder runs in.
Dependencies should be kept to a minimum, because they need to be installed
in each target environment.
"""
87 changes: 87 additions & 0 deletions spyder_unittest/backend/workers/print_versions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# -*- coding: utf-8 -*-
#
# Copyright © Spyder Project Contributors
# Licensed under the terms of the MIT License
# (see LICENSE.txt for details)
"""
Script for checking which test frameworks are installed.
This script prints a dictionary with the required info to stdout.
"""


def get_pytest_info():
"""Return information about pytest."""
try:
import pytest
except ImportError:
return {'available': False}

plugins = {}

class GetPluginVersionsPlugin():
def pytest_cmdline_main(self, config):
nonlocal plugins
plugininfo = config.pluginmanager.list_plugin_distinfo()
plugins = {dist.project_name: dist.version
for plugin, dist in plugininfo}
return 0 # stop pytest, don't collect or run tests

# --capture=sys needed on Windows to avoid
# ValueError: saved filedescriptor not valid anymore
pytest.main(['--capture=sys'],
plugins=[GetPluginVersionsPlugin()])

return {'available': True,
'version': pytest.__version__,
'plugins': plugins}


def get_nose_info():
"""Return information about nose."""
from pkg_resources import iter_entry_points
try:
import nose
except ImportError:
return {'available': False}

plugins = {}
for entry_point, _ in (nose.plugins.manager.EntryPointPluginManager
.entry_points):
for ep in iter_entry_points(entry_point):
plugins[ep.dist.project_name] = ep.dist.version

return {'available': True,
'version': nose.__version__,
'plugins': plugins}


def get_unittest_info():
"""
Return versions of framework and its plugins.
As 'unittest' is a built-in framework, we use the python version.
"""
from platform import python_version
return {'available': True,
'version': python_version(),
'plugins': {}}


def get_all_info():
"""
Return information about all testing frameworks.
Information is returned as a dictionary like the following:
{'pytest': {'available': True, 'version': '7.1.1',
'plugins': {'flaky': '3.7.0', 'pytest-mock': '3.6.1'}},
'nose': {'available': False},
'unittest': {'available': True, 'version': '3.10.5', 'plugins': {}}}
"""
return {'pytest': get_pytest_info(),
'nose': get_nose_info(),
'unittest': get_unittest_info()}


if __name__ == '__main__':
print(get_all_info())
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@
# to execute in a different env with only spyder-kernel installed
try:
# this line is needed for the tests to succeed
from .zmqstream import ZmqStreamWriter
from .zmqwriter import ZmqStreamWriter
except:
# this line is needed for the plugin to work
from zmqstream import ZmqStreamWriter
from zmqwriter import ZmqStreamWriter

class FileStub():
"""Stub for ZmqStreamWriter which instead writes to a file."""
Expand Down
Loading

0 comments on commit 94126d8

Please sign in to comment.