Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6cd1ddd

Browse files
committed
Merge pull request #4668 from jenshnielsen/setuppy_test_deps
TST: Remove test dependencies from install_requires
2 parents beaca96 + f757166 commit 6cd1ddd

File tree

10 files changed

+185
-32
lines changed

10 files changed

+185
-32
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ doc/_build
3535
dist
3636
# Egg metadata
3737
*.egg-info
38+
.eggs
3839
# tox testing tool
3940
.tox
4041

.travis.yml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ env:
2525
- secure: E7OCdqhZ+PlwJcn+Hd6ns9TDJgEUXiUNEI0wu7xjxB2vBRRIKtZMbuaZjd+iKDqCKuVOJKu0ClBUYxmgmpLicTwi34CfTUYt6D4uhrU+8hBBOn1iiK51cl/aBvlUUrqaRLVhukNEBGZcyqAjXSA/Qsnp2iELEmAfOUa92ZYo1sk=
2626
- secure: "dfjNqGKzQG5bu3FnDNwLG8H/C4QoieFo4PfFmZPdM2RY7WIzukwKFNT6kiDfOrpwt+2bR7FhzjOGlDECGtlGOtYPN8XuXGjhcP4a4IfakdbDfF+D3NPIpf5VlE6776k0VpvcZBTMYJKNFIMc7QPkOwjvNJ2aXyfe3hBuGlKJzQU="
2727
- BUILD_DOCS=false
28-
- TEST_ARGS=--no-pep8
2928
- NUMPY=numpy
3029
- NPROC=2
30+
- TEST_ARGS=--omit-pep8
3131

3232
language: python
3333

@@ -40,7 +40,7 @@ matrix:
4040
- python: 3.3
4141
- python: 3.4
4242
- python: 2.7
43-
env: TEST_ARGS=--pep8
43+
env: TEST_ARGS=--pep8-only
4444
- python: 2.7
4545
env: BUILD_DOCS=true MOCK=mock
4646
- python: "nightly"
@@ -109,9 +109,7 @@ script:
109109
- |
110110
if [[ $BUILD_DOCS == false ]]; then
111111
export MPL_REPO_DIR=$PWD # needed for pep8-conformance test of the examples
112-
mkdir ../tmp_test_dir
113-
cd ../tmp_test_dir
114-
gdb -return-child-result -batch -ex r -ex bt --args python ../matplotlib/tests.py -s --processes=$NPROC --process-timeout=300 $TEST_ARGS
112+
gdb -return-child-result -batch -ex r -ex bt --args python setup.py test --nocapture --processes=$NPROC --process-timeout=300 $TEST_ARGS
115113
else
116114
cd doc
117115
python make.py html --small --warningsaserrors

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ jdh_doc_snapshot:
4545

4646

4747
test:
48-
${PYTHON} tests.py
48+
${PYTHON} setup.py test
4949

5050

5151
test-coverage:
52-
${PYTHON} tests.py --with-coverage --cover-package=matplotlib
52+
${PYTHON} setup.py test --with-coverage --cover-package=matplotlib
5353

5454

README.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,12 @@ Testing
2020

2121
After installation, you can launch the test suite::
2222

23-
python tests.py
23+
python setup.py test
24+
25+
Or from the python interpreter::
26+
27+
import matplotlib
28+
matplotlib.test()
2429

2530
Consider reading http://matplotlib.org/devel/coding_guide.html#testing for
2631
more information.

doc/devel/release_guide.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ A guide for developers who are doing a matplotlib release.
1313
Testing
1414
=======
1515

16-
* Run all of the regression tests by running the `tests.py` script at
17-
the root of the source tree.
16+
* Run all of the regression tests by running ``python setup.py test`` script
17+
at the root of the source tree.
1818

1919
* Run :file:`unit/memleak_hawaii3.py` and make sure there are no
2020
memory leaks

doc/devel/testing.rst

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,24 @@ Running the tests
3737
-----------------
3838

3939
Running the tests is simple. Make sure you have nose installed and run
40-
the script :file:`tests.py` in the root directory of the distribution.
41-
The script can take any of the usual `nosetest arguments`_, such as
40+
the setup script's ``test`` command::
4241

43-
=================== ===========
44-
``-v`` increase verbosity
45-
``-d`` detailed error messages
46-
``--with-coverage`` enable collecting coverage information
47-
=================== ===========
42+
python setup.py test
43+
44+
in the root directory of the distribution. The script takes a set of
45+
commands, such as:
46+
47+
======================== ===========
48+
``--pep8-only`` pep8 checks
49+
``--omit-pep8`` Do not perform pep8 checks
50+
``--nocapture`` do not capture stdout (nosetests)
51+
``--nose-verbose`` be verbose (nosetests)
52+
``--processes`` number of processes (nosetests)
53+
``--process-timeout`` process timeout (nosetests)
54+
``--with-coverage`` with coverage
55+
``--detailed-error-msg`` detailed error message (nosetest)
56+
``--tests`` comma separated selection of tests (nosetest)
57+
======================== ===========
4858

4959
Additionally it is possible to run only coding standard test or disable them:
5060

@@ -57,28 +67,30 @@ To run a single test from the command line, you can provide a
5767
dot-separated path to the module followed by the function separated by
5868
a colon, e.g., (this is assuming the test is installed)::
5969

60-
python tests.py matplotlib.tests.test_simplification:test_clipping
61-
62-
If you want to run the full test suite, but want to save wall time try running the
63-
tests in parallel::
70+
python setup.py test --tests=matplotlib.tests.test_simplification:test_clipping
6471

65-
python ../matplotlib/tests.py -sv --processes=5 --process-timeout=300
72+
If you want to run the full test suite, but want to save wall time try
73+
running the tests in parallel::
6674

67-
as we do on Travis.ci.
75+
python setup.py test --nocapture --nose-verbose --processes=5 --process-timeout=300
6876

6977

7078
An alternative implementation that does not look at command line
71-
arguments works from within Python::
79+
arguments works from within Python is to run the tests from the
80+
matplotlib library function :func:`matplotlib.test`::
7281

7382
import matplotlib
7483
matplotlib.test()
7584

76-
.. _`nosetest arguments`: http://nose.readthedocs.org/en/latest/usage.html
85+
.. hint::
86+
87+
You might need to install nose for this::
88+
89+
pip install nose
7790

7891

79-
Running tests by any means other than `matplotlib.test()`
80-
does not load the nose "knownfailureif" (Known failing tests) plugin,
81-
causing known-failing tests to fail for real.
92+
.. _`nosetest arguments`: http://nose.readthedocs.org/en/latest/usage.html
93+
8294

8395
Writing a simple test
8496
---------------------

lib/matplotlib/__init__.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1449,8 +1449,21 @@ def tk_window_focus():
14491449
]
14501450

14511451

1452+
def verify_test_dependencies():
1453+
try:
1454+
import nose
1455+
try:
1456+
from unittest import mock
1457+
except:
1458+
import mock
1459+
except ImportError:
1460+
print("matplotlib.test requires nose and mock to run.")
1461+
raise
1462+
1463+
14521464
def test(verbosity=1):
14531465
"""run the matplotlib test suite"""
1466+
verify_test_dependencies()
14541467
try:
14551468
import faulthandler
14561469
except ImportError:

setup.py

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
# This needs to be the very first thing to use distribute
99
from distribute_setup import use_setuptools
1010
use_setuptools()
11+
from setuptools.command.test import test as TestCommand
1112

1213
import sys
1314

@@ -121,6 +122,118 @@
121122
'Topic :: Scientific/Engineering :: Visualization',
122123
]
123124

125+
126+
class NoseTestCommand(TestCommand):
127+
"""Invoke unit tests using nose after an in-place build."""
128+
129+
description = "Invoke unit tests using nose after an in-place build."
130+
user_options = [
131+
("pep8-only", None, "pep8 checks"),
132+
("omit-pep8", None, "Do not perform pep8 checks"),
133+
("nocapture", None, "do not capture stdout (nosetests)"),
134+
("nose-verbose", None, "be verbose (nosetests)"),
135+
("processes=", None, "number of processes (nosetests)"),
136+
("process-timeout=", None, "process timeout (nosetests)"),
137+
("with-coverage", None, "with coverage"),
138+
("detailed-error-msg", None, "detailed error message (nosetest)"),
139+
("tests=", None, "comma separated selection of tests (nosetest)"),
140+
]
141+
142+
def initialize_options(self):
143+
self.pep8_only = None
144+
self.omit_pep8 = None
145+
146+
# parameters passed to nose tests
147+
self.processes = None
148+
self.process_timeout = None
149+
self.nose_verbose = None
150+
self.nocapture = None
151+
self.with_coverage = None
152+
self.detailed_error_msg = None
153+
self.tests = None
154+
155+
def finalize_options(self):
156+
self.test_args = []
157+
if self.pep8_only:
158+
self.pep8_only = True
159+
if self.omit_pep8:
160+
self.omit_pep8 = True
161+
162+
if self.pep8_only and self.omit_pep8:
163+
from distutils.errors import DistutilsOptionError
164+
raise DistutilsOptionError(
165+
"You are using several options for the test command in an "
166+
"incompatible manner. Please use either --pep8-only or "
167+
"--omit-pep8"
168+
)
169+
170+
if self.processes:
171+
self.test_args.append("--processes={prc}".format(
172+
prc=self.processes))
173+
174+
if self.process_timeout:
175+
self.test_args.append("--process-timeout={tout}".format(
176+
tout=self.process_timeout))
177+
178+
if self.nose_verbose:
179+
self.test_args.append("--verbose")
180+
181+
if self.nocapture:
182+
self.test_args.append("--nocapture")
183+
184+
if self.with_coverage:
185+
self.test_args.append("--with-coverage")
186+
187+
if self.detailed_error_msg:
188+
self.test_args.append("-d")
189+
190+
if self.tests:
191+
self.test_args.append("--tests={names}".format(names=self.tests))
192+
193+
194+
def run(self):
195+
if self.distribution.install_requires:
196+
self.distribution.fetch_build_eggs(
197+
self.distribution.install_requires)
198+
if self.distribution.tests_require:
199+
self.distribution.fetch_build_eggs(self.distribution.tests_require)
200+
201+
self.announce('running unittests with nose')
202+
self.with_project_on_sys_path(self.run_tests)
203+
204+
205+
def run_tests(self):
206+
import matplotlib
207+
matplotlib.use('agg')
208+
import nose
209+
from matplotlib.testing.noseclasses import KnownFailure
210+
from matplotlib import default_test_modules as testmodules
211+
from matplotlib import font_manager
212+
import time
213+
# Make sure the font caches are created before starting any possibly
214+
# parallel tests
215+
if font_manager._fmcache is not None:
216+
while not os.path.exists(font_manager._fmcache):
217+
time.sleep(0.5)
218+
plugins = [KnownFailure]
219+
220+
# Nose doesn't automatically instantiate all of the plugins in the
221+
# child processes, so we have to provide the multiprocess plugin
222+
# with a list.
223+
from nose.plugins import multiprocess
224+
multiprocess._instantiate_plugins = plugins
225+
226+
if self.omit_pep8:
227+
testmodules.remove('matplotlib.tests.test_coding_standards')
228+
elif self.pep8_only:
229+
testmodules = ['matplotlib.tests.test_coding_standards']
230+
231+
nose.main(addplugins=[x() for x in plugins],
232+
defaultTest=testmodules,
233+
argv=['nosetests'] + self.test_args,
234+
exit=False)
235+
236+
124237
# One doesn't normally see `if __name__ == '__main__'` blocks in a setup.py,
125238
# however, this is needed on Windows to avoid creating infinite subprocesses
126239
# when using multiprocessing.
@@ -135,6 +248,7 @@
135248
package_dir = {'': 'lib'}
136249
install_requires = []
137250
setup_requires = []
251+
tests_require = []
138252
default_backend = None
139253

140254
# Go through all of the packages and figure out which ones we are
@@ -195,6 +309,7 @@
195309
package_data[key] = list(set(val + package_data[key]))
196310
install_requires.extend(package.get_install_requires())
197311
setup_requires.extend(package.get_setup_requires())
312+
tests_require.extend(package.get_tests_require())
198313

199314
# Write the default matplotlibrc file
200315
if default_backend is None:
@@ -254,11 +369,13 @@
254369
# List third-party Python packages that we require
255370
install_requires=install_requires,
256371
setup_requires=setup_requires,
372+
tests_require=tests_require,
257373

258374
# matplotlib has C/C++ extensions, so it's not zip safe.
259375
# Telling setuptools this prevents it from doing an automatic
260376
# check for zip safety.
261377
zip_safe=False,
378+
cmdclass={'test': NoseTestCommand},
262379

263380
**extra_args
264381
)

setupext.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,12 @@ def get_setup_requires(self):
415415
"""
416416
return []
417417

418+
def get_tests_require(self):
419+
"""
420+
Get a list of Python packages that we require for executing tests.
421+
"""
422+
return []
423+
418424
def _check_for_pkg_config(self, package, include_file, min_version=None,
419425
version=None):
420426
"""
@@ -645,8 +651,8 @@ def check(self):
645651

646652
msgs = []
647653
msg_template = ('{package} is required to run the matplotlib test '
648-
'suite. pip/easy_install may attempt to install it '
649-
'after matplotlib.')
654+
'suite. "setup.py test" will automatically download it.'
655+
' Install {package} to run matplotlib.test()')
650656

651657
bad_nose = msg_template.format(
652658
package='nose %s or later' % self.nose_min_version
@@ -694,8 +700,8 @@ def get_package_data(self):
694700
'sphinxext/tests/tinypages/_static/*',
695701
]}
696702

697-
def get_install_requires(self):
698-
requires = ['nose>=%s' % self.nose_min_version]
703+
def get_tests_require(self):
704+
requires = ['nose>=%s' % self.nose_min_version, 'sphinx']
699705
if not sys.version_info >= (3, 3):
700706
requires += ['mock']
701707
return requires

tox.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ commands =
1313
{envpython} {toxinidir}/tests.py --processes=-1 --process-timeout=300
1414
deps =
1515
nose
16+
mock
1617
numpy

0 commit comments

Comments
 (0)