Hello community,
here is the log from the commit of package python-spyder-unittest for
openSUSE:Factory checked in at 2020-04-02 17:42:58
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-spyder-unittest (Old)
and /work/SRC/openSUSE:Factory/.python-spyder-unittest.new.3248 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-spyder-unittest"
Thu Apr 2 17:42:58 2020 rev:4 rq:790074 version:0.4.0
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-spyder-unittest/python-spyder-unittest.changes
2018-09-20 11:42:05.128834506 +0200
+++
/work/SRC/openSUSE:Factory/.python-spyder-unittest.new.3248/python-spyder-unittest.changes
2020-04-02 17:43:00.437379852 +0200
@@ -1,0 +2,26 @@
+Tue Mar 24 16:06:07 UTC 2020 - Benjamin Greiner <[email protected]>
+
+- add release to provides and obsoletes
+
+-------------------------------------------------------------------
+Mon Mar 23 14:00:10 UTC 2020 - Benjamin Greiner <[email protected]>
+
+- spyder3 is spyder again
+- enable unit tests
+- no python2 package because spyder does not provide one either
+
+-------------------------------------------------------------------
+Thu Jan 30 15:37:08 UTC 2020 - Todd R <[email protected]>
+
+- Update to 0.4.0
+ + Issues Closed
+ * Colours make text hard to read when run in dark mode
+ * Docstrings in test functions confuse unittest's output parser
+ * KeyError: 'test not found'
+ + Pull Requests Merged
+ * PR: Use appropriate colours when Spyder is in dark mode
+ * PR: Allow for unittest tests to have docstrings
+ * PR: Use nodeid provided by pytest in itemcollected hook
+ * PR: Compatibility fixes for Spyder 4
+
+-------------------------------------------------------------------
Old:
----
spyder_unittest-0.3.1.tar.gz
New:
----
spyder_unittest-0.4.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-spyder-unittest.spec ++++++
--- /var/tmp/diff_new_pack.NrTU2z/_old 2020-04-02 17:43:03.201381993 +0200
+++ /var/tmp/diff_new_pack.NrTU2z/_new 2020-04-02 17:43:03.205381996 +0200
@@ -1,7 +1,7 @@
#
# spec file for package python-spyder-unittest
#
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2020 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -12,25 +12,39 @@
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
#
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
+%define skip_python2 1
Name: python-spyder-unittest
-Version: 0.3.1
+Version: 0.4.0
Release: 0
Summary: Plugin to run tests from within the Spyder IDE
License: MIT
Group: Development/Languages/Python
-Url: https://github.com/spyder-ide/spyder-unittest
-Source:
https://files.pythonhosted.org/packages/source/s/spyder-unittest/spyder_unittest-%{version}.tar.gz
+URL: https://github.com/spyder-ide/spyder-unittest
+Source:
https://files.pythonhosted.org/packages/source/s/spyder_unittest/spyder_unittest-%{version}.tar.gz
BuildRequires: %{python_module devel}
BuildRequires: %{python_module setuptools}
BuildRequires: fdupes
BuildRequires: python-rpm-macros
+Requires: python-lxml
+Requires: spyder >= 3
+Provides: spyder3-unittest = %{version}-%{release}
+Obsoletes: spyder3-unittest < %{version}-%{release}
BuildArch: noarch
-
+# SECTION test requirements
+BuildRequires: %{python_module QtPy}
+BuildRequires: %{python_module lxml}
+BuildRequires: %{python_module nose}
+BuildRequires: %{python_module pytest-qt}
+BuildRequires: %{python_module pytest-xvfb}
+BuildRequires: %{python_module pytest}
+BuildRequires: spyder >= 3
+BuildRequires: xdpyinfo
+# /SECTION
%python_subpackages
%description
@@ -40,32 +54,6 @@
This is a plugin for the Spyder IDE that integrates unit test
frameworks. It allows running tests and viewing the results.
-%package -n spyder-unittest
-Summary: Plugin to run tests from within the Spyder IDE
-Group: Development/Languages/Python
-Requires: python-lxml
-Requires: spyder >= 3
-
-%description -n spyder-unittest
-Spyder, the Scientific Python Development Environment, is an
-IDE for researchers, engineers and data analysts.
-
-This is a plugin for the Spyder IDE that integrates unit test
-frameworks. It allows running tests and viewing the results.
-
-%package -n spyder3-unittest
-Summary: Plugin to run tests from within the Spyder3 IDE
-Group: Development/Languages/Python
-Requires: python3-lxml
-Requires: spyder3 >= 3
-
-%description -n spyder3-unittest
-Spyder, the Scientific Python Development Environment, is an
-IDE for researchers, engineers and data analysts.
-
-This is a plugin for the Spyder IDE that integrates unit test
-frameworks. It allows running tests and viewing the results.
-
%prep
%setup -q -n spyder_unittest-%{version}
@@ -76,16 +64,12 @@
%python_install
%python_expand %fdupes %{buildroot}%{$python_sitelib}
-%files -n spyder-unittest
-%defattr(-,root,root,-)
-%doc CHANGELOG.md README.md
-%license LICENSE.txt
-%{python2_sitelib}/*
+%check
+%pytest
-%files -n spyder3-unittest
-%defattr(-,root,root,-)
+%files %{python_files}
%doc CHANGELOG.md README.md
%license LICENSE.txt
-%{python3_sitelib}/*
+%{python_sitelib}/*
%changelog
++++++ spyder_unittest-0.3.1.tar.gz -> spyder_unittest-0.4.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/spyder_unittest-0.3.1/CHANGELOG.md
new/spyder_unittest-0.4.0/CHANGELOG.md
--- old/spyder_unittest-0.3.1/CHANGELOG.md 2018-06-15 23:06:16.000000000
+0200
+++ new/spyder_unittest-0.4.0/CHANGELOG.md 2020-01-07 13:37:43.000000000
+0100
@@ -1,5 +1,27 @@
# History of changes
+## Version 0.4.0 (2020/01/07)
+
+This release updates the plugin to be used with Spyder 4 and fixes some bugs.
+
+### Issues Closed
+
+* [Issue 133](https://github.com/spyder-ide/spyder-unittest/issues/133) -
Colours make text hard to read when run in dark mode ([PR
135](https://github.com/spyder-ide/spyder-unittest/pull/135))
+* [Issue 129](https://github.com/spyder-ide/spyder-unittest/issues/129) -
Docstrings in test functions confuse unittest's output parser ([PR
134](https://github.com/spyder-ide/spyder-unittest/pull/134))
+* [Issue 128](https://github.com/spyder-ide/spyder-unittest/issues/128) -
KeyError: 'test not found' ([PR
132](https://github.com/spyder-ide/spyder-unittest/pull/132))
+
+In this release 3 issues were closed.
+
+### Pull Requests Merged
+
+* [PR 135](https://github.com/spyder-ide/spyder-unittest/pull/135) - PR: Use
appropriate colours when Spyder is in dark mode
([133](https://github.com/spyder-ide/spyder-unittest/issues/133))
+* [PR 134](https://github.com/spyder-ide/spyder-unittest/pull/134) - PR: Allow
for unittest tests to have docstrings
([129](https://github.com/spyder-ide/spyder-unittest/issues/129))
+* [PR 132](https://github.com/spyder-ide/spyder-unittest/pull/132) - PR: Use
nodeid provided by pytest in itemcollected hook
([128](https://github.com/spyder-ide/spyder-unittest/issues/128))
+* [PR 131](https://github.com/spyder-ide/spyder-unittest/pull/131) - PR:
Compatibility fixes for Spyder 4
+
+In this release 4 pull requests were closed.
+
+
## Version 0.3.1 (2018/06/15)
This version fixes some bugs and also includes some cosmetic changes.
@@ -8,13 +30,13 @@
* [Issue 117](https://github.com/spyder-ide/spyder-unittest/issues/117) -
Rename "py.test" to "pytest" throughout ([PR
119](https://github.com/spyder-ide/spyder-unittest/pull/119))
* [Issue 113](https://github.com/spyder-ide/spyder-unittest/issues/113) -
NameError in test file causes internal error ([PR
118](https://github.com/spyder-ide/spyder-unittest/pull/118))
-* [Issue 112](https://github.com/spyder-ide/spyder-unittest/issues/112) -
Plugin confused by tests writing to sys.__stdout__ ([PR
114](https://github.com/spyder-ide/spyder-unittest/pull/114))
+* [Issue 112](https://github.com/spyder-ide/spyder-unittest/issues/112) -
Plugin confused by tests writing to `sys.__stdout__` ([PR
114](https://github.com/spyder-ide/spyder-unittest/pull/114))
In this release 3 issues were closed.
### Pull Requests Merged
-* [PR 121](https://github.com/spyder-ide/spyder-unittest/pull/121) - PR:
Update readme to remove funding appeal, harmonize with other readmes and minor
fixes ([](a few obvious bugs/typos in the text. You can preview the full
changes live over on [my
repo](https://github.com/CAM-Gerlach/spyder-unittest/blob/update-readme/issues/))
+* [PR 121](https://github.com/spyder-ide/spyder-unittest/pull/121) - PR:
Update readme to remove funding appeal, harmonize with other readmes and minor
fixes
* [PR 120](https://github.com/spyder-ide/spyder-unittest/pull/120) - Remove
unused variables when initializing localization
* [PR 119](https://github.com/spyder-ide/spyder-unittest/pull/119) - Replace
'py.test' by 'pytest'
([117](https://github.com/spyder-ide/spyder-unittest/issues/117))
* [PR 118](https://github.com/spyder-ide/spyder-unittest/pull/118) - Use str()
to convert pytest's longrepr to a string
([113](https://github.com/spyder-ide/spyder-unittest/issues/113))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/spyder_unittest-0.3.1/PKG-INFO
new/spyder_unittest-0.4.0/PKG-INFO
--- old/spyder_unittest-0.3.1/PKG-INFO 2018-06-15 23:12:31.000000000 +0200
+++ new/spyder_unittest-0.4.0/PKG-INFO 2020-01-07 15:30:55.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: spyder_unittest
-Version: 0.3.1
+Version: 0.4.0
Summary: Plugin to run tests from within the Spyder IDE
Home-page: https://github.com/spyder-ide/spyder-unittest
Author: Spyder Project Contributors
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/spyder_unittest-0.3.1/README.md
new/spyder_unittest-0.4.0/README.md
--- old/spyder_unittest-0.3.1/README.md 2018-06-15 23:07:26.000000000 +0200
+++ new/spyder_unittest-0.4.0/README.md 2020-01-02 15:38:07.000000000 +0100
@@ -1,5 +1,6 @@
# Spyder-Unittest
+## Project information
[](./LICENSE)
[](https://pypi.org/project/spyder-unittest/)
[](https://www.anaconda.com/download/)
@@ -7,16 +8,18 @@
[](#backers)
[](https://gitter.im/spyder-ide/public)<br>
[](https://github.com/spyder-ide/spyder-unittest)
+
+## Build status
[](https://travis-ci.org/spyder-ide/spyder-unittest)
[](https://ci.appveyor.com/project/spyder-ide/spyder-unittest)
[](https://circleci.com/gh/spyder-ide/spyder-unittest/tree/master)
[](https://coveralls.io/github/spyder-ide/spyder-unittest?branch=master)
+[](https://crowdin.com/project/spyder-unittest)
*Copyright © 2014–2018 Spyder Project Contributors*

-
## Description
Spyder-unittest is a plugin that integrates popular unit test frameworks
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/spyder_unittest-0.3.1/spyder_unittest/__init__.py
new/spyder_unittest-0.4.0/spyder_unittest/__init__.py
--- old/spyder_unittest-0.3.1/spyder_unittest/__init__.py 2018-06-15
23:09:09.000000000 +0200
+++ new/spyder_unittest-0.4.0/spyder_unittest/__init__.py 2020-01-07
13:42:28.000000000 +0100
@@ -8,5 +8,5 @@
# Local imports
from .unittestplugin import UnitTestPlugin as PLUGIN_CLASS
-__version__ = '0.3.1'
+__version__ = '0.4.0'
PLUGIN_CLASS
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/spyder_unittest-0.3.1/spyder_unittest/backend/pytestworker.py
new/spyder_unittest-0.4.0/spyder_unittest/backend/pytestworker.py
--- old/spyder_unittest-0.3.1/spyder_unittest/backend/pytestworker.py
2018-06-06 20:45:39.000000000 +0200
+++ new/spyder_unittest-0.4.0/spyder_unittest/backend/pytestworker.py
2020-01-03 17:11:03.000000000 +0100
@@ -55,14 +55,9 @@
def pytest_itemcollected(self, item):
"""Called by pytest when a test item is collected."""
- nodeid = item.name
- x = item.parent
- while x.parent:
- nodeid = x.name + '::' + nodeid
- x = x.parent
self.writer.write({
'event': 'collected',
- 'nodeid': nodeid
+ 'nodeid': item.nodeid
})
def pytest_runtest_logstart(self, nodeid, location):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/spyder_unittest-0.3.1/spyder_unittest/backend/tests/test_pytestworker.py
new/spyder_unittest-0.4.0/spyder_unittest/backend/tests/test_pytestworker.py
---
old/spyder_unittest-0.3.1/spyder_unittest/backend/tests/test_pytestworker.py
2018-06-06 20:45:39.000000000 +0200
+++
new/spyder_unittest-0.4.0/spyder_unittest/backend/tests/test_pytestworker.py
2020-01-03 17:11:03.000000000 +0100
@@ -52,12 +52,7 @@
def test_spyderplugin_test_itemcollected(plugin):
testitem = EmptyClass()
- testitem.name = 'bar'
- testitem.parent = EmptyClass()
- testitem.parent.name = 'foo.py'
- testitem.parent.parent = EmptyClass
- testitem.parent.parent.name = 'notused'
- testitem.parent.parent.parent = None
+ testitem.nodeid = 'foo.py::bar'
plugin.pytest_itemcollected(testitem)
plugin.writer.write.assert_called_once_with({
'event': 'collected',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/spyder_unittest-0.3.1/spyder_unittest/backend/tests/test_unittestrunner.py
new/spyder_unittest-0.4.0/spyder_unittest/backend/tests/test_unittestrunner.py
---
old/spyder_unittest-0.3.1/spyder_unittest/backend/tests/test_unittestrunner.py
2018-01-27 12:17:11.000000000 +0100
+++
new/spyder_unittest-0.4.0/spyder_unittest/backend/tests/test_unittestrunner.py
2020-01-07 13:43:12.000000000 +0100
@@ -10,10 +10,15 @@
from spyder_unittest.backend.unittestrunner import UnittestRunner
-def test_unittestrunner_load_data():
+def test_unittestrunner_load_data_with_two_tests():
output = """test_isupper (teststringmethods.TestStringMethods) ... ok
test_split (teststringmethods.TestStringMethods) ... ok
-extra text\n"""
+
+----------------------------------------------------------------------
+Ran 2 tests in 0.012s
+
+OK
+"""
runner = UnittestRunner(None)
res = runner.load_data(output)
assert len(res) == 2
@@ -28,10 +33,10 @@
assert res[1].status == 'ok'
assert res[1].name == 'teststringmethods.TestStringMethods.test_split'
assert res[1].message == ''
- assert res[1].extra_text == ['extra text\n']
+ assert res[1].extra_text == []
-def test_unittestrunner_load_data_removes_footer():
+def test_unittestrunner_load_data_with_one_test():
output = """test1 (test_foo.Bar) ... ok
----------------------------------------------------------------------
@@ -59,6 +64,11 @@
File "/somepath/test_foo.py", line 5, in test1
self.assertEqual(1, 2)
AssertionError: 1 != 2
+
+----------------------------------------------------------------------
+Ran 2 tests in 0.012s
+
+FAILED (failures=1)
"""
runner = UnittestRunner(None)
res = runner.load_data(output)
@@ -68,7 +78,32 @@
assert res[0].status == 'FAIL'
assert res[0].name == 'test_foo.Bar.test1'
assert res[0].extra_text[0].startswith('Traceback')
- assert res[0].extra_text[-1].endswith('AssertionError: 1 != 2\n')
+ assert res[0].extra_text[-1].endswith('AssertionError: 1 != 2')
+
+ assert res[1].category == Category.OK
+ assert res[1].status == 'ok'
+ assert res[1].name == 'test_foo.Bar.test2'
+ assert res[1].extra_text == []
+
+
+def test_unittestrunner_load_data_with_comment():
+ output = """test1 (test_foo.Bar)
+comment ... ok
+test2 (test_foo.Bar) ... ok
+
+----------------------------------------------------------------------
+Ran 2 tests in 0.000s
+
+OK
+"""
+ runner = UnittestRunner(None)
+ res = runner.load_data(output)
+ assert len(res) == 2
+
+ assert res[0].category == Category.OK
+ assert res[0].status == 'ok'
+ assert res[0].name == 'test_foo.Bar.test1'
+ assert res[0].extra_text == []
assert res[1].category == Category.OK
assert res[1].status == 'ok'
@@ -76,30 +111,59 @@
assert res[1].extra_text == []
+def test_unittestrunner_load_data_with_fail_and_comment():
+ output = """test1 (test_foo.Bar)
+comment ... FAIL
+
+======================================================================
+FAIL: test1 (test_foo.Bar)
+comment
+----------------------------------------------------------------------
+Traceback (most recent call last):
+ File "/somepath/test_foo.py", line 30, in test1
+ self.assertEqual(1, 2)
+AssertionError: 1 != 2
+
+----------------------------------------------------------------------
+Ran 1 test in 0.000s
+
+FAILED (failures=1)
+"""
+ runner = UnittestRunner(None)
+ res = runner.load_data(output)
+ assert len(res) == 1
+
+ assert res[0].category == Category.FAIL
+ assert res[0].status == 'FAIL'
+ assert res[0].name == 'test_foo.Bar.test1'
+ assert res[0].extra_text[0].startswith('Traceback')
+ assert res[0].extra_text[-1].endswith('AssertionError: 1 != 2')
+
+
def test_try_parse_header_with_ok():
runner = UnittestRunner(None)
- text = 'test_isupper (testfoo.TestStringMethods) ... ok'
- res = runner.try_parse_result(text)
- assert res == ('test_isupper', 'testfoo.TestStringMethods', 'ok', '')
+ lines = ['test_isupper (testfoo.TestStringMethods) ... ok']
+ res = runner.try_parse_result(lines, 0)
+ assert res == (1, 'test_isupper', 'testfoo.TestStringMethods', 'ok', '')
def test_try_parse_header_with_xfail():
runner = UnittestRunner(None)
- text = 'test_isupper (testfoo.TestStringMethods) ... expected failure'
- res = runner.try_parse_result(text)
- assert res == ('test_isupper', 'testfoo.TestStringMethods',
+ lines = ['test_isupper (testfoo.TestStringMethods) ... expected failure']
+ res = runner.try_parse_result(lines, 0)
+ assert res == (1, 'test_isupper', 'testfoo.TestStringMethods',
'expected failure', '')
def test_try_parse_header_with_message():
runner = UnittestRunner(None)
- text = "test_nothing (testfoo.Tests) ... skipped 'msg'"
- res = runner.try_parse_result(text)
- assert res == ('test_nothing', 'testfoo.Tests', 'skipped', 'msg')
+ lines = ["test_nothing (testfoo.Tests) ... skipped 'msg'"]
+ res = runner.try_parse_result(lines, 0)
+ assert res == (1, 'test_nothing', 'testfoo.Tests', 'skipped', 'msg')
def test_try_parse_header_starting_with_digit():
runner = UnittestRunner(None)
- text = '0est_isupper (testfoo.TestStringMethods) ... ok'
- res = runner.try_parse_result(text)
+ lines = ['0est_isupper (testfoo.TestStringMethods) ... ok']
+ res = runner.try_parse_result(lines, 0)
assert res is None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/spyder_unittest-0.3.1/spyder_unittest/backend/unittestrunner.py
new/spyder_unittest-0.4.0/spyder_unittest/backend/unittestrunner.py
--- old/spyder_unittest-0.3.1/spyder_unittest/backend/unittestrunner.py
2018-02-11 22:08:18.000000000 +0100
+++ new/spyder_unittest-0.4.0/spyder_unittest/backend/unittestrunner.py
2020-01-07 13:43:12.000000000 +0100
@@ -36,6 +36,8 @@
"""
Read and parse output from unittest module.
+ Any parsing errors are silently ignored.
+
Returns
-------
list of TestResult
@@ -44,104 +46,96 @@
res = []
lines = output.splitlines()
line_index = 0
- test_index = None
- while line_index < len(lines):
- data = self.try_parse_result(lines[line_index])
+ while lines[line_index]:
+ data = self.try_parse_result(lines, line_index)
if data:
- if data[2] == 'ok':
+ line_index = data[0]
+ if data[3] == 'ok':
cat = Category.OK
- elif data[2] == 'FAIL' or data[2] == 'ERROR':
+ elif data[3] == 'FAIL' or data[3] == 'ERROR':
cat = Category.FAIL
else:
cat = Category.SKIP
- name = '{}.{}'.format(data[1], data[0])
- tr = TestResult(category=cat, status=data[2], name=name,
- message=data[3])
+ name = '{}.{}'.format(data[2], data[1])
+ tr = TestResult(category=cat, status=data[3], name=name,
+ message=data[4])
res.append(tr)
+ else:
line_index += 1
- test_index = -1
- continue
- data = self.try_parse_exception_header(lines, line_index)
+ line_index += 1
+ while not (lines[line_index]
+ and all(c == '-' for c in lines[line_index])):
+ data = self.try_parse_exception_block(lines, line_index)
if data:
line_index = data[0]
test_index = next(
i for i, tr in enumerate(res)
if tr.name == '{}.{}'.format(data[2], data[1]))
-
- data = self.try_parse_footer(lines, line_index)
- if data:
- line_index = data
- test_index = -1
- continue
-
- if test_index is not None:
- res[test_index].extra_text.append(lines[line_index] + '\n')
+ res[test_index].extra_text = data[3]
+ else:
line_index += 1
return res
- def try_parse_result(self, line):
+ def try_parse_result(self, lines, line_index):
"""
- Try to parse a line of text as a test result.
+ Try to parse one or more lines of text as a test result.
Returns
-------
- tuple of str or None
- If line represents a test result, then return a tuple with four
- strings: the name of the test function, the name of the test class,
- the test result, and the reason (if no reason is given, the fourth
- string is empty). Otherwise, return None.
- """
- regexp = (r'([^\d\W]\w*) \(([^\d\W][\w.]*)\) \.\.\. '
- '(ok|FAIL|ERROR|skipped|expected failure|unexpected success)'
- "( '([^']*)')?\Z")
- match = re.match(regexp, line)
+ (int, str, str, str, str) or None
+ If a test result is parsed successfully then return a tuple with
+ the line index of the first line after the test result, the name
+ of the test function, the name of the test class, the test result,
+ and the reason (if no reason is given, the fourth string is empty).
+ Otherwise, return None.
+ """
+ regexp = r'([^\d\W]\w*) \(([^\d\W][\w.]*)\)'
+ match = re.match(regexp, lines[line_index])
if match:
- msg = match.groups()[4] or ''
- return match.groups()[:3] + (msg, )
+ function_name = match.group(1)
+ class_name = match.group(2)
else:
return None
+ while lines[line_index]:
+ regexp = (r' \.\.\. (ok|FAIL|ERROR|skipped|expected failure|'
+ r"unexpected success)( '([^']*)')?\Z")
+ match = re.search(regexp, lines[line_index])
+ if match:
+ result = match.group(1)
+ msg = match.group(3) or ''
+ return (line_index + 1, function_name, class_name, result, msg)
+ line_index += 1
+ return None
- def try_parse_exception_header(self, lines, line_index):
+ def try_parse_exception_block(self, lines, line_index):
"""
- Try to parse the header of an exception in unittest output.
+ Try to parse a block detailing an exception in unittest output.
Returns
-------
- (int, str, str) or None
- If an exception header is parsed successfully, then return a tuple
- with the new line index, the name of the test function, and the
- name of the test class. Otherwise, return None.
+ (int, str, str, list of str) or None
+ If an exception block is parsed successfully, then return a tuple
+ with the line index of the first line after the block, the name of
+ the test function, the name of the test class, and the text of the
+ exception. Otherwise, return None.
"""
- if lines[line_index] != '':
- return None
- if not all(char == '=' for char in lines[line_index + 1]):
+ if not all(char == '=' for char in lines[line_index]):
return None
regexp = r'\w+: ([^\d\W]\w*) \(([^\d\W][\w.]*)\)\Z'
- match = re.match(regexp, lines[line_index + 2])
+ match = re.match(regexp, lines[line_index + 1])
if not match:
return None
- if not all(char == '-' for char in lines[line_index + 3]):
- return None
- return (line_index + 4, ) + match.groups()
-
- def try_parse_footer(self, lines, line_index):
- """
- Try to parse footer of unittest output.
-
- Returns
- -------
- int or None
- New line index if footer is parsed successfully, None otherwise
- """
- if lines[line_index] != '':
- return None
- if not all(char == '-' for char in lines[line_index + 1]):
- return None
- if not re.match(r'^Ran [\d]+ tests? in', lines[line_index + 2]):
- return None
- if lines[line_index + 3] != '':
- return None
- return line_index + 5
+ line_index += 1
+ while not all(char == '-' for char in lines[line_index]):
+ if not lines[line_index]:
+ return None
+ line_index += 1
+ line_index += 1
+ exception_text = []
+ while lines[line_index]:
+ exception_text.append(lines[line_index])
+ line_index += 1
+ return (line_index, match.group(1), match.group(2), exception_text)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/spyder_unittest-0.3.1/spyder_unittest/tests/test_unittestplugin.py
new/spyder_unittest-0.4.0/spyder_unittest/tests/test_unittestplugin.py
--- old/spyder_unittest-0.3.1/spyder_unittest/tests/test_unittestplugin.py
2018-06-06 20:45:39.000000000 +0200
+++ new/spyder_unittest-0.4.0/spyder_unittest/tests/test_unittestplugin.py
2020-01-02 15:38:07.000000000 +0100
@@ -7,6 +7,7 @@
# Third party imports
import pytest
+from spyder.plugins.projects.projecttypes import EmptyProject
# Local imports
from spyder_unittest.unittestplugin import UnitTestPlugin
@@ -18,10 +19,16 @@
from mock import Mock # Python 2
+class PluginForTesting(UnitTestPlugin):
+ CONF_FILE = False
+
+ def __init__(self, parent):
+ UnitTestPlugin.__init__(self, parent)
+
@pytest.fixture
def plugin(qtbot):
"""Set up the unittest plugin."""
- res = UnitTestPlugin(None)
+ res = PluginForTesting(None)
qtbot.addWidget(res)
res.main = Mock()
res.main.get_spyder_pythonpath = lambda: 'fakepythonpath'
@@ -70,9 +77,7 @@
assert plugin.unittestwidget.default_wdir == 'fakecwd'
# Test after opening project, default_wdir is set to project dir
- project = Mock()
- project.CONF = {}
- project.root_path = str(tmpdir)
+ project = EmptyProject(str(tmpdir))
plugin.main.projects.get_active_project = lambda: project
plugin.main.projects.get_active_project_path = lambda: project.root_path
plugin.handle_project_change()
@@ -87,14 +92,12 @@
def test_plugin_config(plugin, tmpdir, qtbot):
# Test config file does not exist and config is empty
- config_file_path = tmpdir.join('.spyproject', 'unittest.ini')
+ config_file_path = tmpdir.join('.spyproject', 'config', 'unittest.ini')
assert not config_file_path.check()
assert plugin.unittestwidget.config is None
# Open project
- project = Mock()
- project.CONF = {}
- project.root_path = str(tmpdir)
+ project = EmptyProject(str(tmpdir))
plugin.main.projects.get_active_project = lambda: project
plugin.main.projects.get_active_project_path = lambda: project.root_path
plugin.handle_project_change()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/spyder_unittest-0.3.1/spyder_unittest/unittestplugin.py
new/spyder_unittest-0.4.0/spyder_unittest/unittestplugin.py
--- old/spyder_unittest-0.3.1/spyder_unittest/unittestplugin.py 2018-02-02
23:12:29.000000000 +0100
+++ new/spyder_unittest-0.4.0/spyder_unittest/unittestplugin.py 2020-01-07
13:43:12.000000000 +0100
@@ -5,14 +5,17 @@
# (see LICENSE.txt for details)
"""Unit testing Plugin."""
+# Standard library imports
+import os.path as osp
+
# Third party imports
from qtpy.QtWidgets import QVBoxLayout
+from spyder.api.plugins import SpyderPluginWidget
from spyder.config.base import get_translation
-from spyder.plugins import SpyderPluginWidget
+from spyder.config.gui import is_dark_interface
from spyder.py3compat import getcwd
from spyder.utils import icon_manager as ima
from spyder.utils.qthelpers import create_action
-from spyder.widgets.projects.config import ProjectConfig
# Local imports
from spyder_unittest.widgets.configdialog import Config
@@ -26,6 +29,7 @@
CONF_SECTION = 'unittest'
CONF_DEFAULTS = [(CONF_SECTION, {'framework': '', 'wdir': ''})]
+ CONF_NAMEMAP = {CONF_SECTION: [(CONF_SECTION, ['framework', 'wdir'])]}
CONF_VERSION = '0.1.0'
def __init__(self, parent):
@@ -36,29 +40,16 @@
`self.register_plugin()`.
"""
SpyderPluginWidget.__init__(self, parent)
- self.main = parent # Spyder 3 compatibility
-
- # Create unit test widget. For compatibility with Spyder 3.x
- # here we check if the plugin has the attributes
- # 'options_button' and 'options_menu'. See issue 83
- if hasattr(self, 'options_button') and hasattr(self, 'options_menu'):
- # Works with Spyder 4.x
- self.unittestwidget = UnitTestWidget(
- self.main,
- options_button=self.options_button,
- options_menu=self.options_menu)
- else:
- # Works with Spyder 3.x
- self.unittestwidget = UnitTestWidget(self.main)
- # Add unit test widget in dockwindow
+ # Create unit test widget and add to dockwindow
+ self.unittestwidget = UnitTestWidget(
+ self.main,
+ options_button=self.options_button,
+ options_menu=self._options_menu)
layout = QVBoxLayout()
layout.addWidget(self.unittestwidget)
self.setLayout(layout)
- # Initialize plugin
- self.initialize_plugin()
-
def update_pythonpath(self):
"""
Update Python path used to run unit tests.
@@ -101,27 +92,33 @@
then use it. If it is not valid (e.g., because the user never
configured testing for this project) or no project is opened, then
invalidate the current test configuration.
+
+ If necessary, patch the project preferences to include this plugin's
+ config options.
"""
project = self.main.projects.get_active_project()
if not project:
self.unittestwidget.set_config_without_emit(None)
return
- try:
- project_conf = project.CONF[self.CONF_SECTION]
- except KeyError:
- project_conf = ProjectConfig(
+ if self.CONF_SECTION not in project.config._name_map:
+ project.config._name_map = project.config._name_map.copy()
+ project.config._name_map.update(self.CONF_NAMEMAP)
+
+ if self.CONF_SECTION not in project.config._configs_map:
+ config_class = project.config.get_config_class()
+ path = osp.join(project.root_path, '.spyproject', 'config')
+ conf = config_class(
name=self.CONF_SECTION,
- root_path=project.root_path,
- filename=self.CONF_SECTION + '.ini',
defaults=self.CONF_DEFAULTS,
+ path=path,
load=True,
version=self.CONF_VERSION)
- project.CONF[self.CONF_SECTION] = project_conf
+ project.config._configs_map[self.CONF_SECTION] = conf
new_config = Config(
- framework=project_conf.get(self.CONF_SECTION, 'framework'),
- wdir=project_conf.get(self.CONF_SECTION, 'wdir'))
+ framework=project.get_option(self.CONF_SECTION, 'framework'),
+ wdir=project.get_option(self.CONF_SECTION, 'wdir'))
if not self.unittestwidget.config_is_valid(new_config):
new_config = None
self.unittestwidget.set_config_without_emit(new_config)
@@ -135,9 +132,9 @@
project = self.main.projects.get_active_project()
if not project:
return
- project_conf = project.CONF[self.CONF_SECTION]
- project_conf.set(self.CONF_SECTION, 'framework', test_config.framework)
- project_conf.set(self.CONF_SECTION, 'wdir', test_config.wdir)
+ project.set_option(self.CONF_SECTION, 'framework',
+ test_config.framework)
+ project.set_option(self.CONF_SECTION, 'wdir', test_config.wdir)
def goto_in_editor(self, filename, lineno):
"""
@@ -174,9 +171,12 @@
def register_plugin(self):
"""Register plugin in Spyder's main window."""
+ super(UnitTestPlugin, self).register_plugin()
+
# Get information from Spyder proper into plugin
self.update_pythonpath()
self.update_default_wdir()
+ self.unittestwidget.use_dark_interface(is_dark_interface())
# Connect to relevant signals
self.main.sig_pythonpath_changed.connect(self.update_pythonpath)
@@ -191,9 +191,6 @@
self.unittestwidget.sig_newconfig.connect(self.save_config)
self.unittestwidget.sig_edit_goto.connect(self.goto_in_editor)
- # Add plugin as dockwidget to main window
- self.main.add_dockwidget(self)
-
# Create action and add it to Spyder's menu
unittesting_act = create_action(
self,
@@ -209,11 +206,8 @@
def refresh_plugin(self):
"""Refresh unit testing widget."""
- # For compatibility with Spyder 3.x here we check if the plugin
- # has the attributes 'options_button' and 'options_menu'. See issue 83
- if hasattr(self, 'options_button') and hasattr(self, 'options_menu'):
- self.options_menu.clear()
- self.get_plugin_actions()
+ self._options_menu.clear()
+ self.get_plugin_actions()
def closing_plugin(self, cancelable=False):
"""Perform actions before parent main window is closed."""
@@ -232,8 +226,6 @@
not valid (or not set), then ask the user to configure. Then
run the tests.
"""
- if self.dockwidget and not self.ismaximized:
- self.dockwidget.setVisible(True)
- self.dockwidget.setFocus()
- self.dockwidget.raise_()
+ if self.dockwidget:
+ self.switch_to_plugin()
self.unittestwidget.maybe_configure_and_start()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/spyder_unittest-0.3.1/spyder_unittest/widgets/datatree.py
new/spyder_unittest-0.4.0/spyder_unittest/widgets/datatree.py
--- old/spyder_unittest-0.3.1/spyder_unittest/widgets/datatree.py
2018-06-15 23:07:26.000000000 +0200
+++ new/spyder_unittest-0.4.0/spyder_unittest/widgets/datatree.py
2020-01-07 13:43:12.000000000 +0100
@@ -34,6 +34,13 @@
Category.PENDING: QBrush(QColor("#C5C5C5"))
}
+COLORS_DARK = {
+ Category.OK: QBrush(QColor("#008000")),
+ Category.FAIL: QBrush(QColor("#C6001E")),
+ Category.SKIP: QBrush(QColor("#505050")),
+ Category.PENDING: QBrush(QColor("#505050"))
+}
+
STATUS_COLUMN = 0
NAME_COLUMN = 1
MESSAGE_COLUMN = 2
@@ -188,6 +195,11 @@
a tuple (row, column, id). The id is TOPLEVEL_ID for top-level items.
For level-2 items, the id is the index of the test in `self.testresults`.
+ Attributes
+ ----------
+ is_dark_interface : bool
+ Whether to use colours appropriate for a dark user interface.
+
Signals
-------
sig_summary(str)
@@ -200,6 +212,7 @@
"""Constructor."""
QAbstractItemModel.__init__(self, parent)
self.abbreviator = Abbreviator()
+ self.is_dark_interface = False
self.testresults = []
try:
self.monospace_font = parent.window().editor.get_plugin_font()
@@ -319,7 +332,10 @@
elif role == Qt.BackgroundRole:
if id == TOPLEVEL_ID:
testresult = self.testresults[row]
- return COLORS[testresult.category]
+ if self.is_dark_interface:
+ return COLORS_DARK[testresult.category]
+ else:
+ return COLORS[testresult.category]
elif role == Qt.TextAlignmentRole:
if id == TOPLEVEL_ID and column == TIME_COLUMN:
return Qt.AlignRight
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/spyder_unittest-0.3.1/spyder_unittest/widgets/tests/test_datatree.py
new/spyder_unittest-0.4.0/spyder_unittest/widgets/tests/test_datatree.py
--- old/spyder_unittest-0.3.1/spyder_unittest/widgets/tests/test_datatree.py
2018-02-17 17:01:21.000000000 +0100
+++ new/spyder_unittest-0.4.0/spyder_unittest/widgets/tests/test_datatree.py
2020-01-07 13:43:12.000000000 +0100
@@ -12,8 +12,8 @@
# Local imports
from spyder_unittest.backend.runnerbase import Category, TestResult
-from spyder_unittest.widgets.datatree import (COLORS, TestDataModel,
- TestDataView)
+from spyder_unittest.widgets.datatree import (COLORS, COLORS_DARK,
+ TestDataModel, TestDataView)
try:
from unittest.mock import Mock
@@ -156,15 +156,19 @@
model.testresults = [res]
assert model.data(model.index(0, 3), Qt.DisplayRole) == ''
-def test_testdatamodel_data_background():
[email protected]('dark', [False, True])
+def test_testdatamodel_data_background(dark):
model = TestDataModel()
+ if dark:
+ model.is_dark_interface = True
res = [TestResult(Category.OK, 'status', 'foo.bar'),
TestResult(Category.FAIL, 'error', 'foo.bar', 'kadoom')]
model.testresults = res
index = model.index(0, 0)
- assert model.data(index, Qt.BackgroundRole) == COLORS[Category.OK]
+ colors = COLORS_DARK if dark else COLORS
+ assert model.data(index, Qt.BackgroundRole) == colors[Category.OK]
index = model.index(1, 2)
- assert model.data(index, Qt.BackgroundRole) == COLORS[Category.FAIL]
+ assert model.data(index, Qt.BackgroundRole) == colors[Category.FAIL]
def test_testdatamodel_data_userrole():
model = TestDataModel()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/spyder_unittest-0.3.1/spyder_unittest/widgets/unittestgui.py
new/spyder_unittest-0.4.0/spyder_unittest/widgets/unittestgui.py
--- old/spyder_unittest-0.3.1/spyder_unittest/widgets/unittestgui.py
2018-06-15 23:07:26.000000000 +0200
+++ new/spyder_unittest-0.4.0/spyder_unittest/widgets/unittestgui.py
2020-01-07 13:43:12.000000000 +0100
@@ -19,7 +19,7 @@
from spyder.config.base import get_conf_path, get_translation
from spyder.utils import icon_manager as ima
from spyder.utils.qthelpers import create_action, create_toolbutton
-from spyder.widgets.variableexplorer.texteditor import TextEditor
+from spyder.plugins.variableexplorer.widgets.texteditor import TextEditor
# Local imports
from spyder_unittest.backend.frameworkregistry import FrameworkRegistry
@@ -88,6 +88,7 @@
self.default_wdir = None
self.pre_test_hook = None
self.testrunner = None
+
self.output = None
self.testdataview = TestDataView(self)
self.testdatamodel = TestDataModel(self)
@@ -146,6 +147,10 @@
"""Set test configuration but do not emit any signal."""
self._config = new_config
+ def use_dark_interface(self, flag):
+ """Set whether widget should use colours appropriate for dark UI."""
+ self.testdatamodel.is_dark_interface = flag
+
def create_actions(self):
"""Create the actions for the unittest widget."""
self.config_action = create_action(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/spyder_unittest-0.3.1/spyder_unittest.egg-info/PKG-INFO
new/spyder_unittest-0.4.0/spyder_unittest.egg-info/PKG-INFO
--- old/spyder_unittest-0.3.1/spyder_unittest.egg-info/PKG-INFO 2018-06-15
23:12:31.000000000 +0200
+++ new/spyder_unittest-0.4.0/spyder_unittest.egg-info/PKG-INFO 2020-01-07
15:30:54.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: spyder-unittest
-Version: 0.3.1
+Version: 0.4.0
Summary: Plugin to run tests from within the Spyder IDE
Home-page: https://github.com/spyder-ide/spyder-unittest
Author: Spyder Project Contributors