Skip to content

Commit

Permalink
Merge pull request #146 from StefRe/feat/dependencies
Browse files Browse the repository at this point in the history
Show version info of test installed frameworks and their plugins
  • Loading branch information
jitseniesen committed Apr 15, 2020
2 parents 5736314 + b6a7b73 commit f88518b
Show file tree
Hide file tree
Showing 9 changed files with 163 additions and 1 deletion.
14 changes: 14 additions & 0 deletions spyder_unittest/backend/noserunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,20 @@ 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):
"""Create argument list for testing process."""
return [
Expand Down
20 changes: 20 additions & 0 deletions spyder_unittest/backend/pytestrunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,26 @@ 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):
"""Create argument list for testing process."""
pyfile = os.path.join(os.path.dirname(__file__), 'pytestworker.py')
Expand Down
14 changes: 14 additions & 0 deletions spyder_unittest/backend/runnerbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,20 @@ def is_installed(cls):
"""
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):
"""
Create argument list for testing process (dummy).
Expand Down
25 changes: 25 additions & 0 deletions spyder_unittest/backend/tests/test_noserunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,28 @@ def test_noserunner_load_data_passing_test_with_stdout(tmpdir):
runner = NoseRunner(None, result_file.strpath)
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']
29 changes: 29 additions & 0 deletions spyder_unittest/backend/tests/test_pytestrunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,3 +178,32 @@ def test_logreport_to_testresult_with_output():
extra_text=txt, filename=osp.join('ham', 'foo.py'),
lineno=24)
assert logreport_to_testresult(report, Config(wdir='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']
7 changes: 7 additions & 0 deletions spyder_unittest/backend/tests/test_unittestrunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,10 @@ 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']
9 changes: 9 additions & 0 deletions spyder_unittest/backend/unittestrunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ 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):
"""Create argument list for testing process."""
return ['-m', self.module, 'discover', '-v']
Expand Down
27 changes: 27 additions & 0 deletions spyder_unittest/widgets/tests/test_unittestgui.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,3 +266,30 @@ def test_stop_running_tests_before_testresult_is_received(qtbot, tmpdir):

assert widget.testdatamodel.rowCount() == 0
assert widget.status_label.text() == ''


def test_show_versions(monkeypatch):
mockQMessageBox = Mock()
monkeypatch.setattr('spyder_unittest.widgets.unittestgui.QMessageBox',
mockQMessageBox)
widget = UnitTestWidget(None)
monkeypatch.setattr(widget.framework_registry.frameworks['nose'],
'is_installed', lambda: False)
monkeypatch.setattr(widget.framework_registry.frameworks['pytest'],
'is_installed', lambda: True)
monkeypatch.setattr(widget.framework_registry.frameworks['unittest'],
'is_installed', lambda: True)
monkeypatch.setattr(widget.framework_registry.frameworks['nose'],
'get_versions', lambda _: [])
monkeypatch.setattr(widget.framework_registry.frameworks['pytest'],
'get_versions',
lambda _: ['pytest 1.2.3', ' plugin1 4.5.6',
' plugin2 7.8.9'])
monkeypatch.setattr(widget.framework_registry.frameworks['unittest'],
'get_versions', lambda _: ['unittest 1.2.3'])
widget.show_versions()
expected = ('Versions of frameworks and their installed plugins:\n\n'
'nose: not available\n\npytest 1.2.3\n plugin1 4.5.6\n '
'plugin2 7.8.9\n\nunittest 1.2.3')
mockQMessageBox.information.assert_called_with(widget, 'Dependencies',
expected)
19 changes: 18 additions & 1 deletion spyder_unittest/widgets/unittestgui.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ def __init__(self, parent, options_button=None, options_menu=None):
self.options_menu.addAction(self.log_action)
self.options_menu.addAction(self.collapse_action)
self.options_menu.addAction(self.expand_action)
self.options_menu.addAction(self.versions_action)

self.options_button = options_button or QToolButton(self)
self.options_button.setIcon(ima.icon('tooloptions'))
Expand Down Expand Up @@ -173,9 +174,14 @@ def create_actions(self):
text=_('Expand all'),
icon=ima.icon('expand'),
triggered=self.testdataview.expandAll)
self.versions_action = create_action(
self,
text=_('Dependencies'),
icon=ima.icon('advanced'),
triggered=self.show_versions)
return [
self.config_action, self.log_action, self.collapse_action,
self.expand_action
self.expand_action, self.versions_action
]

def show_log(self):
Expand All @@ -188,6 +194,17 @@ def show_log(self):
te.show()
te.exec_()

def show_versions(self):
"""Show versions of frameworks and their plugins"""
versions = [_('Versions of frameworks and their installed plugins:')]
for name, runner in sorted(self.framework_registry.frameworks.items()):
version = (runner.get_versions(self) if runner.is_installed()
else None)
versions.append('\n'.join(version) if version else
'{}: {}'.format(name, _('not available')))
QMessageBox.information(self, _('Dependencies'),
_('\n\n'.join(versions)))

def configure(self):
"""Configure tests."""
if self.config:
Expand Down

0 comments on commit f88518b

Please sign in to comment.