Merge ~cjwatson/lazr.delegates:rhinectomy into lazr.delegates:main

Proposed by Colin Watson
Status: Merged
Approved by: Colin Watson
Approved revision: 5e48801f78161f22fa360ec9ad46e2dd3b2f710a
Merged at revision: 5e48801f78161f22fa360ec9ad46e2dd3b2f710a
Proposed branch: ~cjwatson/lazr.delegates:rhinectomy
Merge into: lazr.delegates:main
Diff against target: 291 lines (+102/-26)
7 files modified
.gitignore (+1/-0)
NEWS.rst (+1/-0)
dev/null (+0/-9)
lazr/delegates/tests/test_docs.py (+67/-0)
lazr/delegates/tests/test_python2.py (+2/-9)
setup.py (+0/-6)
tox.ini (+31/-2)
Reviewer Review Type Date Requested Status
Jürgen Gmach Approve
Review via email: mp+412127@code.launchpad.net

Commit message

Test using zope.testrunner rather than nose

Description of the change

`nose` is unmaintained and doesn't work with Python 3.10. There's `nose2`, but using `zope.testrunner` brings this more into line with other lazr.* projects.

Coverage currently appears fairly terrible, but will improve dramatically once we drop Python 2 support. I could have done Python 2 and 3 runs and combined the coverage output, but it didn't seem worth the complexity when we're likely to be dropping Python 2 support from here soon anyway.

Pre-empting an obvious question: I don't necessarily object to using the `pytest` runner instead, but I thought it better to start by using the same thing as most other lazr.* projects, and we can consider switching them all over in one go later.

Python 2.6 support was already dropped in 2015, but apparently accidentally not removed from `setup.py`, and since I needed to adjust how tests are skipped as part of this work in a way that definitely wouldn't work with Python 2.6 I took the opportunity to update that.

To post a comment you must log in.
Revision history for this message
Jürgen Gmach (jugmac00) :
Revision history for this message
Jürgen Gmach (jugmac00) wrote :

LGTM

We can drop the very old Python 3 version in another MP.

I have created a MP based on yours with combined coverage - I never did that before, but I thought it would be fun to try out.

I will propose it once your's have landed.

review: Approve
Revision history for this message
Jürgen Gmach (jugmac00) wrote :

As you said, the coverage looks much better when combined.

Name Stmts Miss Cover Missing
------------------------------------------------------------------------
lazr/delegates/__init__.py 11 0 100%
lazr/delegates/_delegates.py 32 0 100%
lazr/delegates/_passthrough.py 22 0 100%
lazr/delegates/_python2.py 18 0 100%
lazr/delegates/_python3.py 15 0 100%
lazr/delegates/_version.py 1 0 100%
lazr/delegates/docs/__init__.py 0 0 100%
lazr/delegates/tests/__init__.py 0 0 100%
lazr/delegates/tests/test_api.py 12 3 75% 30-31, 35
lazr/delegates/tests/test_docs.py 19 0 100%
lazr/delegates/tests/test_passthrough.py 46 0 100%
lazr/delegates/tests/test_python2.py 94 4 96% 105, 154-155, 159
------------------------------------------------------------------------
TOTAL 270 7 97%

Missing % in test files usually is a sign of a bogus test setup. I think we should have a look once we drop Python 2.

Revision history for this message
Colin Watson (cjwatson) wrote :

Some of these are "else fail" kind of constructs, where I think "# pragma: no cover" would be suitable. But yes, let's check after dropping Python 2.

FYI you can propose MPs based on unlanded ones without having to wait for them to land, by using the "prerequisite branch" facility (this doesn't exist on GitHub so you may not be familiar with it). Though as I mentioned I wonder whether combined coverage is worth the complexity when we'll be dropping Python 2 support anyway?

Revision history for this message
Jürgen Gmach (jugmac00) wrote :

Thanks for the info about "MPs on unlanded ones" - this was indeed new.

I know it would not have been necessary to combine coverage, but as I never did that before, this was a nice fun "project" for the weekend.

Though it turned out it is not that complicated - once you know how it works :-)

This "knowledge" could come handy when we have to combine the coverage results for different Python 3 versions (I look at you Python 3.10 :-) ).

see https://code.launchpad.net/~jugmac00/lazr.delegates/+git/lazr.delegates/+merge/412213

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/.gitignore b/.gitignore
2index daeb903..16ba64f 100644
3--- a/.gitignore
4+++ b/.gitignore
5@@ -11,6 +11,7 @@ build
6 dist
7 __pycache__
8 .coverage
9+htmlcov
10 .tox
11 *.pyc
12 lazr/delegates/docs/_build
13diff --git a/NEWS.rst b/NEWS.rst
14index 731cf96..476c1d4 100644
15--- a/NEWS.rst
16+++ b/NEWS.rst
17@@ -5,6 +5,7 @@ NEWS for lazr.delegates
18 2.0.5
19 =====
20 - Officially add support for Python 3.6, 3.7, and 3.8.
21+- Test using ``zope.testrunner`` rather than ``nose``.
22
23
24 2.0.4 (2017-10-20)
25diff --git a/lazr/delegates/docs/fixture.py b/lazr/delegates/docs/fixture.py
26deleted file mode 100644
27index 1d4aced..0000000
28--- a/lazr/delegates/docs/fixture.py
29+++ /dev/null
30@@ -1,34 +0,0 @@
31-# Copyright 2009-2015 Canonical Ltd. All rights reserved.
32-#
33-# This file is part of lazr.delegates
34-#
35-# lazr.delegates is free software: you can redistribute it and/or modify it
36-# under the terms of the GNU Lesser General Public License as published by
37-# the Free Software Foundation, version 3 of the License.
38-#
39-# lazr.delegates is distributed in the hope that it will be useful, but WITHOUT
40-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
41-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
42-# License for more details.
43-#
44-# You should have received a copy of the GNU Lesser General Public License
45-# along with lazr.delegates. If not, see <http://www.gnu.org/licenses/>.
46-
47-"""Doctest fixtures for running under nose."""
48-
49-from __future__ import absolute_import, print_function, unicode_literals
50-
51-__metaclass__ = type
52-__all__ = [
53- 'globs',
54- ]
55-
56-
57-def globs(globs):
58- """Set up globals for doctests."""
59- # Enable future statements to make Python 2 act more like Python 3.
60- globs['absolute_import'] = absolute_import
61- globs['print_function'] = print_function
62- globs['unicode_literals'] = unicode_literals
63- # Provide a convenient way to clean things up at the end of the test.
64- return globs
65diff --git a/lazr/delegates/docs/usage_fixture.py b/lazr/delegates/docs/usage_fixture.py
66deleted file mode 100644
67index 7012cf7..0000000
68--- a/lazr/delegates/docs/usage_fixture.py
69+++ /dev/null
70@@ -1,27 +0,0 @@
71-# Copyright 2009-2015 Canonical Ltd. All rights reserved.
72-#
73-# This file is part of lazr.delegates
74-#
75-# lazr.delegates is free software: you can redistribute it and/or modify it
76-# under the terms of the GNU Lesser General Public License as published by
77-# the Free Software Foundation, version 3 of the License.
78-#
79-# lazr.delegates is distributed in the hope that it will be useful, but WITHOUT
80-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
81-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
82-# License for more details.
83-#
84-# You should have received a copy of the GNU Lesser General Public License
85-# along with lazr.delegates. If not, see <http://www.gnu.org/licenses/>.
86-
87-"""Doctest fixtures for running under nose."""
88-
89-from __future__ import absolute_import, print_function, unicode_literals
90-
91-__metaclass__ = type
92-__all__ = [
93- 'globs',
94- ]
95-
96-
97-from lazr.delegates.docs.fixture import globs
98diff --git a/lazr/delegates/tests/test_docs.py b/lazr/delegates/tests/test_docs.py
99new file mode 100644
100index 0000000..7ca6971
101--- /dev/null
102+++ b/lazr/delegates/tests/test_docs.py
103@@ -0,0 +1,67 @@
104+# Copyright 2009-2021 Canonical Ltd. All rights reserved.
105+#
106+# This file is part of lazr.delegates.
107+#
108+# lazr.delegates is free software: you can redistribute it and/or modify it
109+# under the terms of the GNU Lesser General Public License as published by
110+# the Free Software Foundation, version 3 of the License.
111+#
112+# lazr.delegates is distributed in the hope that it will be useful, but WITHOUT
113+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
114+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
115+# License for more details.
116+#
117+# You should have received a copy of the GNU Lesser General Public License
118+# along with lazr.delegates. If not, see <http://www.gnu.org/licenses/>.
119+
120+"""Test harness for doctests."""
121+
122+from __future__ import absolute_import, print_function, unicode_literals
123+
124+__metaclass__ = type
125+__all__ = []
126+
127+import atexit
128+import doctest
129+import os
130+
131+from pkg_resources import (
132+ resource_filename,
133+ resource_exists,
134+ resource_listdir,
135+ cleanup_resources,
136+)
137+
138+
139+DOCTEST_FLAGS = (
140+ doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE | doctest.REPORT_NDIFF
141+)
142+
143+
144+def load_tests(loader, tests, pattern):
145+ """Load the doc tests (docs/*, if any exist)."""
146+ doctest_files = []
147+ if resource_exists("lazr.delegates", "docs"):
148+ for name in resource_listdir("lazr.delegates", "docs"):
149+ if name.endswith(".rst"):
150+ doctest_files.append(
151+ os.path.abspath(
152+ resource_filename("lazr.delegates", "docs/%s" % name)
153+ )
154+ )
155+ atexit.register(cleanup_resources)
156+ globs = {
157+ "absolute_import": absolute_import,
158+ "print_function": print_function,
159+ "unicode_literals": unicode_literals,
160+ }
161+ tests.addTest(
162+ doctest.DocFileSuite(
163+ *doctest_files,
164+ module_relative=False,
165+ optionflags=DOCTEST_FLAGS,
166+ globs=globs,
167+ encoding="UTF-8"
168+ )
169+ )
170+ return tests
171diff --git a/lazr/delegates/tests/test_python2.py b/lazr/delegates/tests/test_python2.py
172index 1cc873b..ad3de7e 100644
173--- a/lazr/delegates/tests/test_python2.py
174+++ b/lazr/delegates/tests/test_python2.py
175@@ -63,14 +63,7 @@ class BaseOtherFoo(BaseFoo):
176 another = 'yes, another'
177
178
179-# Python 2.6 doesn't have skips.
180-def skip_python3(cls):
181- if sys.version_info[0] > 2:
182- return None
183- return cls
184-
185-
186-@skip_python3
187+@unittest.skipIf(sys.version_info[0] > 2, "only relevant in Python 2")
188 class TestLegacyAPI(unittest.TestCase):
189 def test_basic_usage(self):
190 class SomeClass(object):
191@@ -146,7 +139,7 @@ class TestLegacyAPI(unittest.TestCase):
192 self.assertTrue(IOther.providedBy(foo_with_teapot))
193
194
195-@skip_python3
196+@unittest.skipIf(sys.version_info[0] > 2, "only relevant in Python 2")
197 class TestNewAPI(unittest.TestCase):
198 """Test corner cases in Python 2.
199
200diff --git a/setup.cfg b/setup.cfg
201deleted file mode 100644
202index 0af9456..0000000
203--- a/setup.cfg
204+++ /dev/null
205@@ -1,9 +0,0 @@
206-[nosetests]
207-verbosity=3
208-with-coverage=1
209-with-doctest=1
210-doctest-extension=.rst
211-doctest-options=+ELLIPSIS,+NORMALIZE_WHITESPACE,+REPORT_NDIFF
212-doctest-fixtures=_fixture
213-cover-package=lazr.delegates
214-pdb=1
215diff --git a/setup.py b/setup.py
216index f0fe050..f8b5b24 100755
217--- a/setup.py
218+++ b/setup.py
219@@ -37,7 +37,6 @@ delegating behavior.
220 """,
221 license='LGPL v3',
222 install_requires=[
223- 'nose',
224 'setuptools',
225 'zope.interface',
226 ],
227@@ -50,7 +49,6 @@ delegating behavior.
228 "Operating System :: OS Independent",
229 'Programming Language :: Python',
230 'Programming Language :: Python :: 2',
231- 'Programming Language :: Python :: 2.6',
232 'Programming Language :: Python :: 2.7',
233 'Programming Language :: Python :: 3',
234 'Programming Language :: Python :: 3.2',
235@@ -64,8 +62,4 @@ delegating behavior.
236 extras_require={
237 "docs": ["Sphinx"],
238 },
239- # nose plugins don't really work with `python setup.py test` so use
240- # `python setup.py nosetests` instead, or just `tox`. Gosh, we really
241- # should switch to nose2. :/ - BAW 2014-08-20
242- #test_suite='nose.collector',
243 )
244diff --git a/tox.ini b/tox.ini
245index 76a9117..f30fd94 100644
246--- a/tox.ini
247+++ b/tox.ini
248@@ -1,8 +1,21 @@
249 [tox]
250-envlist = py27,py32,py33,py34,py35,py36,py37,py38
251+envlist =
252+ py27
253+ py32
254+ py33
255+ py34
256+ py35
257+ py36
258+ py37
259+ py38
260+ coverage
261
262 [testenv]
263-commands = python setup.py nosetests
264+deps =
265+ .
266+ zope.testrunner
267+commands =
268+ zope-testrunner --test-path . --tests-pattern ^tests {posargs}
269
270 [testenv:docs]
271 basepython =
272@@ -11,3 +24,19 @@ commands =
273 sphinx-build -b html -d lazr/delegates/docs/_build/doctrees lazr/delegates/docs lazr/delegates/docs/_build/html
274 deps =
275 .[docs]
276+
277+[testenv:coverage]
278+basepython =
279+ python3
280+deps =
281+ coverage
282+ zope.testrunner
283+commands =
284+ coverage erase
285+ coverage run -m zope.testrunner --test-path . --tests-pattern ^tests {posargs}
286+ coverage html
287+ coverage report -m --fail-under=56
288+
289+[coverage:run]
290+source = lazr.delegates
291+omit = */docs/conf.py

Subscribers

People subscribed via source and target branches

to all changes: