From 362c271ea101be04854ae4c33007fa7989e0e822 Mon Sep 17 00:00:00 2001 From: Nikita Kniazev Date: Tue, 12 Jul 2016 18:33:17 +0300 Subject: [PATCH] Prepare for cross-framework test suite - introduced `xfail(reason)` function - uses: `raise KnownFailureTest(msg)` -> `xfail(reason)` - same name and signature as in pytest - introduced `skip(reason)` function - uses: `raise SkipTest(msg)` -> `skip(reason)` - same name and signature as in pytest - introduced `skipif(condition, reason=None)` decorator - uses: replaces `def func(): if condition: skip()` - same name and signature as in pytest - can be used with functions, classes, and methods - supports string condition (evaluated at runtime) - moved nose related code to `testing.nose` submodule - plugins in `testing.nose.plugins` submodule - decorators implementation in `testing.nose.decorators` (interface is still in `testing.decorators`, implementation will have been chosen at runtime according to used test framework) - `matplotlib.test` function unifications - `tests.py` now uses `matplotlib.test()` --- lib/matplotlib/__init__.py | 65 ++-------------- lib/matplotlib/testing/__init__.py | 44 +++++++++++ lib/matplotlib/testing/decorators.py | 58 +++++---------- lib/matplotlib/testing/exceptions.py | 12 --- lib/matplotlib/testing/nose/__init__.py | 70 ++++++++++++++++++ lib/matplotlib/testing/nose/decorators.py | 74 +++++++++++++++++++ lib/matplotlib/testing/nose/exceptions.py | 10 +++ .../testing/nose/plugins/__init__.py | 0 .../plugins/knownfailure.py} | 6 +- .../testing/{ => nose/plugins}/performgc.py | 0 lib/matplotlib/tests/test_animation.py | 14 ++-- lib/matplotlib/tests/test_axes.py | 7 +- lib/matplotlib/tests/test_backend_pgf.py | 7 +- lib/matplotlib/tests/test_basic.py | 46 +++++++++++- lib/matplotlib/tests/test_coding_standards.py | 7 +- lib/matplotlib/tests/test_image.py | 1 - tests.py | 33 ++------- 17 files changed, 286 insertions(+), 168 deletions(-) create mode 100644 lib/matplotlib/testing/nose/__init__.py create mode 100644 lib/matplotlib/testing/nose/decorators.py create mode 100644 lib/matplotlib/testing/nose/exceptions.py create mode 100644 lib/matplotlib/testing/nose/plugins/__init__.py rename lib/matplotlib/testing/{noseclasses.py => nose/plugins/knownfailure.py} (90%) rename lib/matplotlib/testing/{ => nose/plugins}/performgc.py (100%) diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py index 6f69f8f46165..aa701bfd3e0f 100644 --- a/lib/matplotlib/__init__.py +++ b/lib/matplotlib/__init__.py @@ -1398,7 +1398,7 @@ def use(arg, warn=True, force=False): if 'matplotlib.backends' in sys.modules: # Warn only if called with a different name if (rcParams['backend'] != name) and warn: - warnings.warn(_use_error_msg) + warnings.warn(_use_error_msg, stacklevel=2) # Unless we've been told to force it, just return if not force: @@ -1580,70 +1580,17 @@ def _init_tests(): ) ) - try: - import nose - try: - from unittest import mock - except: - import mock - except ImportError: - print("matplotlib.test requires nose and mock to run.") - raise - - -def _get_extra_test_plugins(): - from .testing.performgc import PerformGC - from .testing.noseclasses import KnownFailure - from nose.plugins import attrib + from .testing.nose import check_deps + check_deps() - return [PerformGC, KnownFailure, attrib.Plugin] - -def _get_nose_env(): - env = {'NOSE_COVER_PACKAGE': 'matplotlib', - 'NOSE_COVER_HTML': 1, - 'NOSE_COVER_NO_PRINT': 1} - return env - - -def test(verbosity=1, coverage=False): +def test(verbosity=1, coverage=False, **kwargs): """run the matplotlib test suite""" _init_tests() - old_backend = rcParams['backend'] - try: - use('agg') - import nose - import nose.plugins.builtin - from nose.plugins.manager import PluginManager - from nose.plugins import multiprocess - - # store the old values before overriding - plugins = _get_extra_test_plugins() - plugins.extend([plugin for plugin in nose.plugins.builtin.plugins]) - - manager = PluginManager(plugins=[x() for x in plugins]) - config = nose.config.Config(verbosity=verbosity, plugins=manager) - - # Nose doesn't automatically instantiate all of the plugins in the - # child processes, so we have to provide the multiprocess plugin with - # a list. - multiprocess._instantiate_plugins = plugins - - env = _get_nose_env() - if coverage: - env['NOSE_WITH_COVERAGE'] = 1 - - success = nose.run( - defaultTest=default_test_modules, - config=config, - env=env, - ) - finally: - if old_backend.lower() != 'agg': - use(old_backend) + from .testing.nose import test as nose_test + return nose_test(verbosity, coverage, **kwargs) - return success test.__test__ = False # nose: this function is not a test diff --git a/lib/matplotlib/testing/__init__.py b/lib/matplotlib/testing/__init__.py index 76de517f18a1..f47171652d10 100644 --- a/lib/matplotlib/testing/__init__.py +++ b/lib/matplotlib/testing/__init__.py @@ -1,6 +1,7 @@ from __future__ import (absolute_import, division, print_function, unicode_literals) +import inspect import warnings from contextlib import contextmanager @@ -13,6 +14,49 @@ def _is_list_like(obj): return not is_string_like(obj) and iterable(obj) +def xfail(msg=""): + """Explicitly fail an currently-executing test with the given message.""" + from .nose import knownfail + knownfail(msg) + + +def skip(msg=""): + """Skip an executing test with the given message.""" + from nose import SkipTest + raise SkipTest(msg) + + +# stolen from pytest +def getrawcode(obj, trycall=True): + """Return code object for given function.""" + try: + return obj.__code__ + except AttributeError: + obj = getattr(obj, 'im_func', obj) + obj = getattr(obj, 'func_code', obj) + obj = getattr(obj, 'f_code', obj) + obj = getattr(obj, '__code__', obj) + if trycall and not hasattr(obj, 'co_firstlineno'): + if hasattr(obj, '__call__') and not inspect.isclass(obj): + x = getrawcode(obj.__call__, trycall=False) + if hasattr(x, 'co_firstlineno'): + return x + return obj + + +def copy_metadata(src_func, tgt_func): + """Replicates metadata of the function. Returns target function.""" + tgt_func.__dict__ = src_func.__dict__ + tgt_func.__doc__ = src_func.__doc__ + tgt_func.__module__ = src_func.__module__ + tgt_func.__name__ = src_func.__name__ + if hasattr(src_func, '__qualname__'): + tgt_func.__qualname__ = src_func.__qualname__ + if not hasattr(tgt_func, 'compat_co_firstlineno'): + tgt_func.compat_co_firstlineno = getrawcode(src_func).co_firstlineno + return tgt_func + + # stolen from pandas @contextmanager def assert_produces_warning(expected_warning=Warning, filter_level="always", diff --git a/lib/matplotlib/testing/decorators.py b/lib/matplotlib/testing/decorators.py index ffa17173c9f1..c79d6e5fbbc1 100644 --- a/lib/matplotlib/testing/decorators.py +++ b/lib/matplotlib/testing/decorators.py @@ -4,7 +4,6 @@ import six import functools -import gc import inspect import os import sys @@ -12,9 +11,6 @@ import warnings import unittest -import nose -import numpy as np - import matplotlib as mpl import matplotlib.style import matplotlib.units @@ -24,13 +20,23 @@ from matplotlib import pyplot as plt from matplotlib import ft2font from matplotlib import rcParams -from matplotlib.testing.noseclasses import KnownFailureTest, \ - KnownFailureDidNotFailTest, ImageComparisonFailure from matplotlib.testing.compare import comparable_formats, compare_images, \ make_test_filename +from . import copy_metadata, skip, xfail +from .exceptions import ImageComparisonFailure + + +def skipif(condition, *args, **kwargs): + """Skip the given test function if eval(condition) results in a True + value. + + Optionally specify a reason for better reporting. + """ + from .nose.decorators import skipif + return skipif(condition, *args, **kwargs) -def knownfailureif(fail_condition, msg=None, known_exception_class=None ): +def knownfailureif(fail_condition, msg=None, known_exception_class=None): """ Assume a will fail if *fail_condition* is True. *fail_condition* @@ -42,32 +48,8 @@ def knownfailureif(fail_condition, msg=None, known_exception_class=None ): if the exception is an instance of this class. (Default = None) """ - # based on numpy.testing.dec.knownfailureif - if msg is None: - msg = 'Test known to fail' - def known_fail_decorator(f): - # Local import to avoid a hard nose dependency and only incur the - # import time overhead at actual test-time. - import nose - def failer(*args, **kwargs): - try: - # Always run the test (to generate images). - result = f(*args, **kwargs) - except Exception as err: - if fail_condition: - if known_exception_class is not None: - if not isinstance(err,known_exception_class): - # This is not the expected exception - raise - # (Keep the next ultra-long comment so in shows in console.) - raise KnownFailureTest(msg) # An error here when running nose means that you don't have the matplotlib.testing.noseclasses:KnownFailure plugin in use. - else: - raise - if fail_condition and fail_condition != 'indeterminate': - raise KnownFailureDidNotFailTest(msg) - return result - return nose.tools.make_decorator(f)(failer) - return known_fail_decorator + from .nose.decorators import knownfailureif + return knownfailureif(fail_condition, msg, known_exception_class) def _do_cleanup(original_units_registry, original_settings): @@ -211,7 +193,7 @@ def remove_text(figure): def test(self): baseline_dir, result_dir = _image_directories(self._func) if self._style != 'classic': - raise KnownFailureTest('temporarily disabled until 2.0 tag') + xfail('temporarily disabled until 2.0 tag') for fignum, baseline in zip(plt.get_fignums(), self._baseline_images): for extension in self._extensions: will_fail = not extension in comparable_formats() @@ -263,13 +245,14 @@ def do_test(): '(RMS %(rms).3f)'%err) except ImageComparisonFailure: if not check_freetype_version(self._freetype_version): - raise KnownFailureTest( + xfail( "Mismatched version of freetype. Test requires '%s', you have '%s'" % (self._freetype_version, ft2font.__freetype_version__)) raise yield (do_test,) + def image_comparison(baseline_images=None, extensions=None, tol=0, freetype_version=None, remove_text=False, savefig_kwarg=None, style='classic'): @@ -428,7 +411,7 @@ def backend_switcher(*args, **kwargs): plt.switch_backend(prev_backend) return result - return nose.tools.make_decorator(func)(backend_switcher) + return copy_metadata(func, backend_switcher) return switch_backend_decorator @@ -447,7 +430,6 @@ def skip_if_command_unavailable(cmd): try: check_output(cmd) except: - from nose import SkipTest - raise SkipTest('missing command: %s' % cmd[0]) + skip('missing command: %s' % cmd[0]) return lambda f: f diff --git a/lib/matplotlib/testing/exceptions.py b/lib/matplotlib/testing/exceptions.py index b549d89205ec..c39a39207747 100644 --- a/lib/matplotlib/testing/exceptions.py +++ b/lib/matplotlib/testing/exceptions.py @@ -1,15 +1,3 @@ -class KnownFailureTest(Exception): - """ - Raise this exception to mark a test as a known failing test. - """ - - -class KnownFailureDidNotFailTest(Exception): - """ - Raise this exception to mark a test should have failed but did not. - """ - - class ImageComparisonFailure(AssertionError): """ Raise this exception to mark a test as a comparison between two images. diff --git a/lib/matplotlib/testing/nose/__init__.py b/lib/matplotlib/testing/nose/__init__.py new file mode 100644 index 000000000000..df3ec0b23692 --- /dev/null +++ b/lib/matplotlib/testing/nose/__init__.py @@ -0,0 +1,70 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + + +def get_extra_test_plugins(): + from .plugins.performgc import PerformGC + from .plugins.knownfailure import KnownFailure + from nose.plugins import attrib + + return [PerformGC, KnownFailure, attrib.Plugin] + + +def get_env(): + env = {'NOSE_COVER_PACKAGE': 'matplotlib', + 'NOSE_COVER_HTML': 1, + 'NOSE_COVER_NO_PRINT': 1} + return env + + +def check_deps(): + try: + import nose + try: + from unittest import mock + except ImportError: + import mock + except ImportError: + print("matplotlib.test requires nose and mock to run.") + raise + + +def test(verbosity=None, coverage=False, switch_backend_warn=True, **kwargs): + from ... import default_test_modules, get_backend, use + + old_backend = get_backend() + try: + use('agg') + import nose + from nose.plugins import multiprocess + + # Nose doesn't automatically instantiate all of the plugins in the + # child processes, so we have to provide the multiprocess plugin with + # a list. + extra_plugins = get_extra_test_plugins() + multiprocess._instantiate_plugins = extra_plugins + + env = get_env() + if coverage: + env['NOSE_WITH_COVERAGE'] = 1 + + if verbosity is not None: + env['NOSE_VERBOSE'] = verbosity + + success = nose.run( + addplugins=[plugin() for plugin in extra_plugins], + env=env, + defaultTest=default_test_modules, + **kwargs + ) + finally: + if old_backend.lower() != 'agg': + use(old_backend, warn=switch_backend_warn) + + return success + + +def knownfail(msg): + from .exceptions import KnownFailureTest + # Keep the next ultra-long comment so it shows in console. + raise KnownFailureTest(msg) # An error here when running nose means that you don't have the matplotlib.testing.nose.plugins:KnownFailure plugin in use. # noqa diff --git a/lib/matplotlib/testing/nose/decorators.py b/lib/matplotlib/testing/nose/decorators.py new file mode 100644 index 000000000000..d6456b76424e --- /dev/null +++ b/lib/matplotlib/testing/nose/decorators.py @@ -0,0 +1,74 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import os +import six +import sys +from .. import copy_metadata, skip +from . import knownfail +from .exceptions import KnownFailureDidNotFailTest + + +def skipif(skip_condition, *args, **kwargs): + if isinstance(skip_condition, bool) and 'reason' not in kwargs: + raise ValueError("you need to specify reason=STRING " + "when using booleans as conditions.") + + def skip_decorator(func): + import inspect + + def skipper(*_args, **_kwargs): + condition, msg = skip_condition, kwargs.get('reason') # local copy + if isinstance(condition, six.string_types): + globs = {'os': os, 'sys': sys} + try: + globs.update(func.__globals__) + except AttributeError: + globs.update(func.func_globals) + if msg is None: + msg = condition + condition = eval(condition, globs) + else: + condition = bool(condition) + + if condition: + skip(msg) + else: + return func(*_args, **_kwargs) + + if inspect.isclass(func): + setup = getattr(func, 'setup_class', classmethod(lambda _: None)) + setup = skip_decorator(setup.__func__) + setup = setup.__get__(func) + setattr(func, 'setup_class', setup) + return func + + return copy_metadata(func, skipper) + + return skip_decorator + + +def knownfailureif(fail_condition, msg=None, known_exception_class=None): + # based on numpy.testing.dec.knownfailureif + if msg is None: + msg = 'Test known to fail' + + def known_fail_decorator(f): + def failer(*args, **kwargs): + try: + # Always run the test (to generate images). + result = f(*args, **kwargs) + except Exception as err: + if fail_condition: + if known_exception_class is not None: + if not isinstance(err, known_exception_class): + # This is not the expected exception + raise + knownfail(msg) + else: + raise + if fail_condition and fail_condition != 'indeterminate': + raise KnownFailureDidNotFailTest(msg) + return result + return copy_metadata(f, failer) + return known_fail_decorator diff --git a/lib/matplotlib/testing/nose/exceptions.py b/lib/matplotlib/testing/nose/exceptions.py new file mode 100644 index 000000000000..51fc6f782d78 --- /dev/null +++ b/lib/matplotlib/testing/nose/exceptions.py @@ -0,0 +1,10 @@ +class KnownFailureTest(Exception): + """ + Raise this exception to mark a test as a known failing test. + """ + + +class KnownFailureDidNotFailTest(Exception): + """ + Raise this exception to mark a test should have failed but did not. + """ diff --git a/lib/matplotlib/testing/nose/plugins/__init__.py b/lib/matplotlib/testing/nose/plugins/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/lib/matplotlib/testing/noseclasses.py b/lib/matplotlib/testing/nose/plugins/knownfailure.py similarity index 90% rename from lib/matplotlib/testing/noseclasses.py rename to lib/matplotlib/testing/nose/plugins/knownfailure.py index 8bcb09d28a29..3a5c86c35048 100644 --- a/lib/matplotlib/testing/noseclasses.py +++ b/lib/matplotlib/testing/nose/plugins/knownfailure.py @@ -1,13 +1,9 @@ from __future__ import (absolute_import, division, print_function, unicode_literals) -import six - import os from nose.plugins.errorclass import ErrorClass, ErrorClassPlugin -from matplotlib.testing.exceptions import (KnownFailureTest, - KnownFailureDidNotFailTest, - ImageComparisonFailure) +from ..exceptions import KnownFailureTest class KnownFailure(ErrorClassPlugin): diff --git a/lib/matplotlib/testing/performgc.py b/lib/matplotlib/testing/nose/plugins/performgc.py similarity index 100% rename from lib/matplotlib/testing/performgc.py rename to lib/matplotlib/testing/nose/plugins/performgc.py diff --git a/lib/matplotlib/tests/test_animation.py b/lib/matplotlib/tests/test_animation.py index 7a63de9d640f..c6373584ce2d 100644 --- a/lib/matplotlib/tests/test_animation.py +++ b/lib/matplotlib/tests/test_animation.py @@ -8,14 +8,12 @@ import tempfile import numpy as np from numpy.testing import assert_equal -from nose import with_setup from nose.tools import assert_false, assert_true import matplotlib as mpl from matplotlib import pyplot as plt from matplotlib import animation -from matplotlib.testing.noseclasses import KnownFailureTest -from matplotlib.testing.decorators import cleanup -from matplotlib.testing.decorators import CleanupTest +from ..testing import xfail, skip +from ..testing.decorators import cleanup class NullMovieWriter(animation.AbstractMovieWriter): @@ -113,8 +111,7 @@ def test_save_animation_smoketest(): @cleanup def check_save_animation(writer, extension='mp4'): if not animation.writers.is_available(writer): - raise KnownFailureTest("writer '%s' not available on this system" - % writer) + skip("writer '%s' not available on this system" % writer) fig, ax = plt.subplots() line, = ax.plot([], []) @@ -138,9 +135,8 @@ def animate(i): try: anim.save(F.name, fps=30, writer=writer, bitrate=500) except UnicodeDecodeError: - raise KnownFailureTest("There can be errors in the numpy " + - "import stack, " + - "see issues #1891 and #2679") + xfail("There can be errors in the numpy import stack, " + "see issues #1891 and #2679") finally: try: os.remove(F.name) diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 650b6078631a..c56dc621eb16 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -22,8 +22,7 @@ import warnings import matplotlib -from matplotlib.testing.decorators import image_comparison, cleanup -from matplotlib.testing.noseclasses import KnownFailureTest +from matplotlib.testing.decorators import image_comparison, cleanup, skipif import matplotlib.pyplot as plt import matplotlib.markers as mmarkers import matplotlib.patches as mpatches @@ -87,10 +86,10 @@ def test_formatter_ticker(): ax.autoscale_view() +@skipif(LooseVersion(np.__version__) >= LooseVersion('1.11.0'), + reason="Fall out from a fixed numpy bug") @image_comparison(baseline_images=["formatter_large_small"]) def test_formatter_large_small(): - if LooseVersion(np.__version__) >= LooseVersion('1.11.0'): - raise KnownFailureTest("Fall out from a fixed numpy bug") # github issue #617, pull #619 fig, ax = plt.subplots(1) x = [0.500000001, 0.500000002] diff --git a/lib/matplotlib/tests/test_backend_pgf.py b/lib/matplotlib/tests/test_backend_pgf.py index 36315d185262..a86f4de53226 100644 --- a/lib/matplotlib/tests/test_backend_pgf.py +++ b/lib/matplotlib/tests/test_backend_pgf.py @@ -2,13 +2,10 @@ from __future__ import (absolute_import, division, print_function, unicode_literals) -import six - import os import shutil import numpy as np -import nose from nose.plugins.skip import SkipTest import matplotlib as mpl @@ -17,7 +14,7 @@ from matplotlib.testing.compare import compare_images, ImageComparisonFailure from matplotlib.testing.decorators import (_image_directories, switch_backend, cleanup) -from matplotlib.testing.noseclasses import KnownFailureTest +from ..testing import xfail baseline_dir, result_dir = _image_directories(lambda: 'dummy func') @@ -44,7 +41,7 @@ def check_for(texsystem): def compare_figure(fname, savefig_kwargs={}, tol=0): # TODO remove this before tagging 2.0 - raise KnownFailureTest('temporarily disabled until 2.0 tag') + xfail('temporarily disabled until 2.0 tag') actual = os.path.join(result_dir, fname) plt.savefig(actual, **savefig_kwargs) diff --git a/lib/matplotlib/tests/test_basic.py b/lib/matplotlib/tests/test_basic.py index d5f23ba868aa..a5f3a33ba785 100644 --- a/lib/matplotlib/tests/test_basic.py +++ b/lib/matplotlib/tests/test_basic.py @@ -5,10 +5,17 @@ from nose.tools import assert_equal -from matplotlib.testing.decorators import knownfailureif +from ..testing.decorators import knownfailureif, skipif from pylab import * +SKIPIF_CONDITION = [] + + +def setup_module(): + SKIPIF_CONDITION.append(None) + + def test_simple(): assert_equal(1 + 1, 2) @@ -19,8 +26,41 @@ def test_simple_knownfail(): assert_equal(1 + 1, 3) +@skipif(True, reason="skipif decorator test with bool condition passed") +def test_skipif_bool(): + assert False, "skipif decorator does not work with bool condition" + + +@skipif('SKIPIF_CONDITION', + reason="skipif decorator test with string condition passed") +def test_skipif_string(): + assert False, "skipif decorator does not work with string condition" + + +@skipif(True, reason="skipif decorator on class test passed") +class Test_skipif_on_class(object): + def test(self): + assert False, "skipif decorator does not work on classes" + + +class Test_skipif_on_method(object): + @skipif(True, reason="skipif decorator on method test passed") + def test(self): + assert False, "skipif decorator does not work on methods" + + +@skipif(True, reason="skipif decorator on classmethod test passed") +class Test_skipif_on_classmethod(object): + @classmethod + def setup_class(cls): + pass + + def test(self): + assert False, "skipif decorator does not work on classmethods" + + def test_override_builtins(): - ok_to_override = set([ + ok_to_override = { '__name__', '__doc__', '__package__', @@ -29,7 +69,7 @@ def test_override_builtins(): 'any', 'all', 'sum' - ]) + } # We could use six.moves.builtins here, but that seems # to do a little more than just this. diff --git a/lib/matplotlib/tests/test_coding_standards.py b/lib/matplotlib/tests/test_coding_standards.py index f1aff0e589e1..6862ee2fed99 100644 --- a/lib/matplotlib/tests/test_coding_standards.py +++ b/lib/matplotlib/tests/test_coding_standards.py @@ -6,7 +6,7 @@ from nose.tools import assert_equal from nose.plugins.skip import SkipTest -from matplotlib.testing.noseclasses import KnownFailureTest +from ..testing import xfail try: import pep8 @@ -256,9 +256,8 @@ def test_pep8_conformance_examples(): fp, tail = os.path.split(fp) if mpldir is None: - raise KnownFailureTest("can not find the examples, set env " - "MPL_REPO_DIR to point to the top-level path " - "of the source tree") + xfail("can not find the examples, set env MPL_REPO_DIR to point " + "to the top-level path of the source tree") exdir = os.path.join(mpldir, 'examples') blacklist = () diff --git a/lib/matplotlib/tests/test_image.py b/lib/matplotlib/tests/test_image.py index e06328440f2a..851f9cffb775 100644 --- a/lib/matplotlib/tests/test_image.py +++ b/lib/matplotlib/tests/test_image.py @@ -22,7 +22,6 @@ from nose.tools import assert_raises from numpy.testing import ( assert_array_equal, assert_array_almost_equal, assert_allclose) -from matplotlib.testing.noseclasses import KnownFailureTest from copy import copy from numpy import ma import matplotlib.colors as colors diff --git a/tests.py b/tests.py index db19f5572772..d6c179ed31e5 100755 --- a/tests.py +++ b/tests.py @@ -9,43 +9,19 @@ # See https://nose.readthedocs.org/ for a detailed description of # these options. -import os import sys -import time -import matplotlib -matplotlib.use('agg') - -import nose -from matplotlib import default_test_modules - - -def run(extra_args): - from nose.plugins import multiprocess - - env = matplotlib._get_nose_env() - - matplotlib._init_tests() - - # Nose doesn't automatically instantiate all of the plugins in the - # child processes, so we have to provide the multiprocess plugin with - # a list. - plugins = matplotlib._get_extra_test_plugins() - multiprocess._instantiate_plugins = plugins - - nose.main(addplugins=[x() for x in plugins], - defaultTest=default_test_modules, - argv=sys.argv + extra_args, - env=env) if __name__ == '__main__': + from matplotlib import default_test_modules, test + extra_args = [] if '--no-pep8' in sys.argv: default_test_modules.remove('matplotlib.tests.test_coding_standards') sys.argv.remove('--no-pep8') elif '--pep8' in sys.argv: - default_test_modules = ['matplotlib.tests.test_coding_standards'] + default_test_modules[:] = ['matplotlib.tests.test_coding_standards'] sys.argv.remove('--pep8') if '--no-network' in sys.argv: from matplotlib.testing import disable_internet @@ -55,4 +31,5 @@ def run(extra_args): print('Python byte-compilation optimization level: %d' % sys.flags.optimize) - run(extra_args) + success = test(argv=sys.argv + extra_args, switch_backend_warn=False) + sys.exit(not success)