diff options
77 files changed, 699 insertions, 603 deletions
diff --git a/.appveyor.yml b/.appveyor.yml index 091767a1c..f001aa041 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -8,10 +8,6 @@ max_jobs: 100 cache: - '%LOCALAPPDATA%\pip\Cache' -matrix: - allow_failures: - - USE_PYTEST: true - environment: global: MINGW_32: C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin @@ -27,7 +23,7 @@ environment: - PYTHON: C:\Python34-x64 PYTHON_VERSION: 3.4 PYTHON_ARCH: 64 - USE_PYTEST: true + TEST_MODE: fast - PYTHON: C:\Python36 PYTHON_VERSION: 3.6 @@ -107,30 +103,27 @@ build_script: # Here, we add MinGW to the path to be able to link an OpenBLAS.dll # We then use the import library from the DLL to compile with MSVC - ps: | - If ($env:USE_PYTEST -eq "true") { - pip install -e . - } Else { - pip wheel -v -v -v --wheel-dir=dist . - - # For each wheel that pip has placed in the "dist" directory - # First, upload the wheel to the "artifacts" tab and then - # install the wheel. If we have only built numpy (as is the case here), - # then there will be one wheel to install. - - # This method is more representative of what will be distributed, - # because it actually tests what the built wheels will be rather than - # what 'setup.py install' will do and at it uploads the wheels so that - # they can be inspected. - - ls dist -r | Foreach-Object { - appveyor PushArtifact $_.FullName - pip install $_.FullName - } + pip wheel -v -v -v --wheel-dir=dist . + + # For each wheel that pip has placed in the "dist" directory + # First, upload the wheel to the "artifacts" tab and then + # install the wheel. If we have only built numpy (as is the case here), + # then there will be one wheel to install. + + # This method is more representative of what will be distributed, + # because it actually tests what the built wheels will be rather than + # what 'setup.py install' will do and at it uploads the wheels so that + # they can be inspected. + + ls dist -r | Foreach-Object { + Push-AppveyorArtifact $_.FullName + pip install $_.FullName } test_script: - - if [%USE_PYTEST%]==[true] pytest -n3 --junitxml=junit-results.xml - - if [%USE_PYTEST%]==[] python runtests.py -v -n -m %TEST_MODE% + #- if [%USE_PYTEST%]==[true] pytest -n3 --junitxml=junit-results.xml + #- if [%USE_PYTEST%]==[] python runtests.py -v -n -m %TEST_MODE% + python runtests.py -v -n -m %TEST_MODE% -- --disable-pytest-warnings after_build: # Remove old or huge cache files to hopefully not exceed the 1GB cache limit. diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 000000000..1f61c25a4 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,3 @@ +[run] +branch = True +include = */numpy/* diff --git a/doc/release/1.15.0-notes.rst b/doc/release/1.15.0-notes.rst index 46ffb7913..5cb32d929 100644 --- a/doc/release/1.15.0-notes.rst +++ b/doc/release/1.15.0-notes.rst @@ -6,6 +6,8 @@ NumPy 1.15.0 Release Notes Highlights ========== +* NumPy has switched to pytest for testing. + New functions ============= @@ -37,6 +39,13 @@ Deprecations * `np.ma.loads`, `np.ma.dumps` * `np.ma.load`, `np.ma.dump` - these functions already failed on python 3, when called with a string. +* Direct imports from the following modules is deprecated. All testing related + imports should come from `numpy.testing`. + * `np.testing.utils` + * `np.testing.decorators` + * `np.testing.nosetester` + * `np.testing.noseclasses` + * `np.core.umath_tests` * Giving a generator to `np.sum` is now deprecated. This was undocumented, but worked. Previously, it would calculate the sum of the generator expression. @@ -51,6 +60,16 @@ Future Changes Compatibility notes =================== +Numpy has switched to using pytest instead of nose for testing +-------------------------------------------------------------- +The last nose release was 1.3.7 in June, 2015, and development of that tool has +ended, consequently NumPy has now switched to using pytest. The old decorators +and nose tools that were previously used by some downstream projects remain +available, but will not be maintained. The standard testing utilities, +`assert_almost_equal` and such, are not be affected by this change except for +the nose specific functions `import_nose` and `raises`. Those functions are +not used in numpy, but are kept for downstream compatibility. + ``np.ma.notmasked_contiguous`` and ``np.ma.flatnotmasked_contiguous`` always return lists ----------------------------------------------------------------------------------------- This was always the documented behavior, but in reality the result used to be @@ -86,7 +105,6 @@ builtin arbitrary-precision `Decimal` and `long` types. Support for cross-platform builds for iOS ----------------------------------------- - The build system has been modified to add support for the ``_PYTHON_HOST_PLATFORM`` environment variable, used by ``distutils`` when compiling on one platform for another platform. This makes it possible to diff --git a/numpy/__init__.py b/numpy/__init__.py index db7bc0368..d10a1ecd3 100644 --- a/numpy/__init__.py +++ b/numpy/__init__.py @@ -146,11 +146,6 @@ else: pkgload.__doc__ = PackageLoader.__call__.__doc__ - # We don't actually use this ourselves anymore, but I'm not 100% sure that - # no-one else in the world is using it (though I hope not) - from .testing import Tester, _numpy_tester - test = _numpy_tester().test - # Allow distributors to run custom init code from . import _distributor_init @@ -186,13 +181,16 @@ else: __all__.extend(lib.__all__) __all__.extend(['linalg', 'fft', 'random', 'ctypeslib', 'ma']) - - # Filter annoying Cython warnings that serve no good purpose. - warnings.filterwarnings("ignore", message="numpy.dtype size changed") - warnings.filterwarnings("ignore", message="numpy.ufunc size changed") - warnings.filterwarnings("ignore", message="numpy.ndarray size changed") - # oldnumeric and numarray were removed in 1.9. In case some packages import # but do not use them, we define them here for backward compatibility. oldnumeric = 'removed' numarray = 'removed' + + # We don't actually use this ourselves anymore, but I'm not 100% sure that + # no-one else in the world is using it (though I hope not) + from .testing import Tester + + # Pytest testing + from numpy.testing._private.pytesttester import PytestTester + test = PytestTester(__name__) + del PytestTester diff --git a/numpy/conftest.py b/numpy/conftest.py index ce985d079..7b1771748 100644 --- a/numpy/conftest.py +++ b/numpy/conftest.py @@ -15,6 +15,7 @@ _old_fpu_mode = None _collect_results = {} +#FIXME when yield tests are gone. @pytest.hookimpl() def pytest_itemcollected(item): """ @@ -52,35 +53,10 @@ def check_fpu_mode(request): if collect_result is not None: old_mode, new_mode = collect_result raise AssertionError("FPU precision mode changed from {0:#x} to {1:#x}" - " when collecting the test".format(old_mode, + " when collecting the test".format(old_mode, new_mode)) -def pytest_addoption(parser): - parser.addoption("--runslow", action="store_true", - default=False, help="run slow tests") - - -def pytest_collection_modifyitems(config, items): - if config.getoption("--runslow"): - # --runslow given in cli: do not skip slow tests - return - skip_slow = pytest.mark.skip(reason="need --runslow option to run") - for item in items: - if "slow" in item.keywords: - item.add_marker(skip_slow) - - @pytest.fixture(autouse=True) def add_np(doctest_namespace): doctest_namespace['np'] = numpy - - -for module, replacement in { - 'numpy.testing.decorators': 'numpy.testing.pytest_tools.decorators', - 'numpy.testing.utils': 'numpy.testing.pytest_tools.utils', -}.items(): - module = importlib.import_module(module) - replacement = importlib.import_module(replacement) - module.__dict__.clear() - module.__dict__.update(replacement.__dict__) diff --git a/numpy/core/__init__.py b/numpy/core/__init__.py index 264324503..4d9cbf5da 100644 --- a/numpy/core/__init__.py +++ b/numpy/core/__init__.py @@ -70,10 +70,6 @@ __all__ += getlimits.__all__ __all__ += shape_base.__all__ __all__ += einsumfunc.__all__ - -from numpy.testing import _numpy_tester -test = _numpy_tester().test - # Make it possible so that ufuncs can be pickled # Here are the loading and unloading functions # The name numpy.core._ufunc_reconstruct must be @@ -103,3 +99,7 @@ copyreg.pickle(ufunc, _ufunc_reduce, _ufunc_reconstruct) del copyreg del sys del _ufunc_reduce + +from numpy.testing._private.pytesttester import PytestTester +test = PytestTester(__name__) +del PytestTester diff --git a/numpy/core/tests/test_arrayprint.py b/numpy/core/tests/test_arrayprint.py index 6c2403e67..189eabf9b 100644 --- a/numpy/core/tests/test_arrayprint.py +++ b/numpy/core/tests/test_arrayprint.py @@ -1,12 +1,15 @@ # -*- coding: utf-8 -*- from __future__ import division, absolute_import, print_function -import sys, gc +import sys +import gc +import pytest import numpy as np from numpy.testing import ( - run_module_suite, assert_, assert_equal, assert_raises, assert_warns, dec, -) + run_module_suite, assert_, assert_equal, assert_raises, assert_warns, + HAS_REFCOUNT, + ) import textwrap class TestArrayRepr(object): @@ -34,7 +37,7 @@ class TestArrayRepr(object): " [(1,), (1,)]], dtype=[('a', '<i4')])" ) - @dec.knownfailureif(True, "See gh-10544") + @pytest.mark.xfail(reason="See gh-10544") def test_object_subclass(self): class sub(np.ndarray): def __new__(cls, inp): @@ -388,7 +391,7 @@ class TestArray2String(object): "[ 'xxxxx']" ) - @dec._needs_refcount + @pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts") def test_refcount(self): # make sure we do not hold references to the array due to a recursive # closure (gh-10620) diff --git a/numpy/core/tests/test_datetime.py b/numpy/core/tests/test_datetime.py index ba291737a..f660d8869 100644 --- a/numpy/core/tests/test_datetime.py +++ b/numpy/core/tests/test_datetime.py @@ -5,9 +5,10 @@ import pickle import numpy import numpy as np import datetime +import pytest from numpy.testing import ( run_module_suite, assert_, assert_equal, assert_raises, - assert_warns, dec, suppress_warnings + assert_warns, suppress_warnings ) # Use pytz to test out various time zones if available @@ -1487,7 +1488,7 @@ class TestDateTime(object): np.datetime64('2032-01-01T00:00:00', 'us'), unit='auto'), '2032-01-01') - @dec.skipif(not _has_pytz, "The pytz module is not available.") + @pytest.mark.skipif(not _has_pytz, reason="The pytz module is not available.") def test_datetime_as_string_timezone(self): # timezone='local' vs 'UTC' a = np.datetime64('2010-03-15T06:30', 'm') diff --git a/numpy/core/tests/test_deprecations.py b/numpy/core/tests/test_deprecations.py index cc4c058d1..f055b5fcd 100644 --- a/numpy/core/tests/test_deprecations.py +++ b/numpy/core/tests/test_deprecations.py @@ -9,11 +9,12 @@ import datetime import sys import operator import warnings +import pytest import numpy as np from numpy.testing import ( run_module_suite, assert_raises, assert_warns, assert_no_warnings, - assert_array_equal, assert_, dec) + assert_array_equal, assert_) try: import pytz @@ -242,7 +243,8 @@ class TestDatetime64Timezone(_DeprecationTestCase): self.assert_deprecated(np.datetime64, args=('2000-01-01T00+01',)) self.assert_deprecated(np.datetime64, args=('2000-01-01T00Z',)) - @dec.skipif(not _has_pytz, "The pytz module is not available.") + @pytest.mark.skipif(not _has_pytz, + reason="The pytz module is not available.") def test_datetime(self): tz = pytz.timezone('US/Eastern') dt = datetime.datetime(2000, 1, 1, 0, 0, tzinfo=tz) diff --git a/numpy/core/tests/test_dtype.py b/numpy/core/tests/test_dtype.py index c924e6f43..f8a724832 100644 --- a/numpy/core/tests/test_dtype.py +++ b/numpy/core/tests/test_dtype.py @@ -3,12 +3,12 @@ from __future__ import division, absolute_import, print_function import pickle import sys import operator +import pytest import numpy as np from numpy.core._rational_tests import rational from numpy.testing import ( - run_module_suite, assert_, assert_equal, assert_raises, - dec + run_module_suite, assert_, assert_equal, assert_raises ) def assert_dtype_equal(a, b): @@ -593,7 +593,7 @@ class TestString(object): assert_equal(repr(dt), "dtype([('a', '<M8[D]'), ('b', '<m8[us]')])") - @dec.skipif(sys.version_info[0] >= 3) + @pytest.mark.skipif(sys.version_info[0] >= 3, reason="Python 2 only") def test_dtype_str_with_long_in_shape(self): # Pull request #376, should not error np.dtype('(1L,)i4') diff --git a/numpy/core/tests/test_errstate.py b/numpy/core/tests/test_errstate.py index ae06af7fd..212073362 100644 --- a/numpy/core/tests/test_errstate.py +++ b/numpy/core/tests/test_errstate.py @@ -1,13 +1,14 @@ from __future__ import division, absolute_import, print_function import platform +import pytest import numpy as np -from numpy.testing import assert_, run_module_suite, dec +from numpy.testing import assert_, run_module_suite class TestErrstate(object): - @dec.skipif(platform.machine() == "armv5tel", "See gh-413.") + @pytest.mark.skipif(platform.machine() == "armv5tel", reason="See gh-413.") def test_invalid(self): with np.errstate(all='raise', under='ignore'): a = -np.arange(3) diff --git a/numpy/core/tests/test_extint128.py b/numpy/core/tests/test_extint128.py index 31786124d..b041fb0d5 100644 --- a/numpy/core/tests/test_extint128.py +++ b/numpy/core/tests/test_extint128.py @@ -4,12 +4,13 @@ import sys import itertools import contextlib import operator +import pytest import numpy as np import numpy.core._multiarray_tests as mt from numpy.compat import long -from numpy.testing import assert_raises, assert_equal, dec +from numpy.testing import assert_raises, assert_equal INT64_MAX = np.iinfo(np.int64).max @@ -183,7 +184,7 @@ def test_gt_128(): assert_equal(d, c) -@dec.slow +@pytest.mark.slow def test_divmod_128_64(): with exc_iter(INT128_VALUES, INT64_POS_VALUES) as it: for a, b in it: diff --git a/numpy/core/tests/test_half.py b/numpy/core/tests/test_half.py index 813cf9572..080f136a5 100644 --- a/numpy/core/tests/test_half.py +++ b/numpy/core/tests/test_half.py @@ -1,10 +1,11 @@ from __future__ import division, absolute_import, print_function import platform +import pytest import numpy as np from numpy import uint16, float16, float32, float64 -from numpy.testing import run_module_suite, assert_, assert_equal, dec +from numpy.testing import run_module_suite, assert_, assert_equal def assert_raises_fpe(strmatch, callable, *args, **kwargs): @@ -355,7 +356,8 @@ class TestHalf(object): assert_equal(np.power(b32, a16).dtype, float16) assert_equal(np.power(b32, b16).dtype, float32) - @dec.skipif(platform.machine() == "armv5tel", "See gh-413.") + @pytest.mark.skipif(platform.machine() == "armv5tel", + reason="See gh-413.") def test_half_fpe(self): with np.errstate(all='raise'): sx16 = np.array((1e-4,), dtype=float16) diff --git a/numpy/core/tests/test_indexing.py b/numpy/core/tests/test_indexing.py index 082ecb496..01330ac55 100644 --- a/numpy/core/tests/test_indexing.py +++ b/numpy/core/tests/test_indexing.py @@ -4,13 +4,14 @@ import sys import warnings import functools import operator +import pytest import numpy as np from numpy.core._multiarray_tests import array_indexing from itertools import product from numpy.testing import ( run_module_suite, assert_, assert_equal, assert_raises, - assert_array_equal, assert_warns, dec, HAS_REFCOUNT, suppress_warnings, + assert_array_equal, assert_warns, HAS_REFCOUNT, suppress_warnings, ) @@ -608,7 +609,7 @@ class TestSubclasses(object): assert_array_equal(new_s.finalize_status, new_s) assert_array_equal(new_s.old, s) - @dec._needs_refcount + @pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts") def test_slice_decref_getsetslice(self): # See gh-10066, a temporary slice object should be discarted. # This test is only really interesting on Python 2 since diff --git a/numpy/core/tests/test_longdouble.py b/numpy/core/tests/test_longdouble.py index 7cd5b04d8..302bfe9ec 100644 --- a/numpy/core/tests/test_longdouble.py +++ b/numpy/core/tests/test_longdouble.py @@ -1,10 +1,10 @@ from __future__ import division, absolute_import, print_function -import locale +import pytest import numpy as np from numpy.testing import ( - run_module_suite, assert_, assert_equal, dec, assert_raises, + run_module_suite, assert_, assert_equal, assert_raises, assert_array_equal, temppath, ) from ._locales import CommaDecimalPointLocale @@ -30,8 +30,8 @@ def test_scalar_extraction(): # 0.1 not exactly representable in base 2 floating point. repr_precision = len(repr(np.longdouble(0.1))) # +2 from macro block starting around line 842 in scalartypes.c.src. -@dec.skipif(LD_INFO.precision + 2 >= repr_precision, - "repr precision not enough to show eps") +@pytest.mark.skipif(LD_INFO.precision + 2 >= repr_precision, + reason="repr precision not enough to show eps") def test_repr_roundtrip(): # We will only see eps in repr if within printing precision. o = 1 + LD_INFO.eps @@ -50,7 +50,7 @@ def test_bytes(): np.longdouble(b"1.2") -@dec.knownfailureif(string_to_longdouble_inaccurate, "Need strtold_l") +@pytest.mark.skipif(string_to_longdouble_inaccurate, reason="Need strtold_l") def test_repr_roundtrip_bytes(): o = 1 + LD_INFO.eps assert_equal(np.longdouble(repr(o).encode("ascii")), o) @@ -61,7 +61,7 @@ def test_bogus_string(): assert_raises(ValueError, np.longdouble, "1.0 flub") -@dec.knownfailureif(string_to_longdouble_inaccurate, "Need strtold_l") +@pytest.mark.skipif(string_to_longdouble_inaccurate, reason="Need strtold_l") def test_fromstring(): o = 1 + LD_INFO.eps s = (" " + repr(o))*5 @@ -98,7 +98,8 @@ class TestFileBased(object): res = np.fromfile(path, dtype=float, sep=" ") assert_equal(res, np.array([1., 2., 3.])) - @dec.knownfailureif(string_to_longdouble_inaccurate, "Need strtold_l") + @pytest.mark.skipif(string_to_longdouble_inaccurate, + reason="Need strtold_l") def test_fromfile(self): with temppath() as path: with open(path, 'wt') as f: @@ -106,7 +107,8 @@ class TestFileBased(object): res = np.fromfile(path, dtype=np.longdouble, sep="\n") assert_equal(res, self.tgt) - @dec.knownfailureif(string_to_longdouble_inaccurate, "Need strtold_l") + @pytest.mark.skipif(string_to_longdouble_inaccurate, + reason="Need strtold_l") def test_genfromtxt(self): with temppath() as path: with open(path, 'wt') as f: @@ -114,7 +116,8 @@ class TestFileBased(object): res = np.genfromtxt(path, dtype=np.longdouble) assert_equal(res, self.tgt) - @dec.knownfailureif(string_to_longdouble_inaccurate, "Need strtold_l") + @pytest.mark.skipif(string_to_longdouble_inaccurate, + reason="Need strtold_l") def test_loadtxt(self): with temppath() as path: with open(path, 'wt') as f: @@ -122,7 +125,8 @@ class TestFileBased(object): res = np.loadtxt(path, dtype=np.longdouble) assert_equal(res, self.tgt) - @dec.knownfailureif(string_to_longdouble_inaccurate, "Need strtold_l") + @pytest.mark.skipif(string_to_longdouble_inaccurate, + reason="Need strtold_l") def test_tofile_roundtrip(self): with temppath() as path: self.tgt.tofile(path, sep=" ") @@ -138,22 +142,26 @@ def test_repr_exact(): assert_(repr(o) != '1') -@dec.knownfailureif(longdouble_longer_than_double, "BUG #2376") -@dec.knownfailureif(string_to_longdouble_inaccurate, "Need strtold_l") +@pytest.mark.skipif(longdouble_longer_than_double, reason="BUG #2376") +@pytest.mark.skipif(string_to_longdouble_inaccurate, + reason="Need strtold_l") def test_format(): o = 1 + LD_INFO.eps assert_("{0:.40g}".format(o) != '1') -@dec.knownfailureif(longdouble_longer_than_double, "BUG #2376") -@dec.knownfailureif(string_to_longdouble_inaccurate, "Need strtold_l") +@pytest.mark.skipif(longdouble_longer_than_double, reason="BUG #2376") +@pytest.mark.skipif(string_to_longdouble_inaccurate, + reason="Need strtold_l") def test_percent(): o = 1 + LD_INFO.eps assert_("%.40g" % o != '1') -@dec.knownfailureif(longdouble_longer_than_double, "array repr problem") -@dec.knownfailureif(string_to_longdouble_inaccurate, "Need strtold_l") +@pytest.mark.skipif(longdouble_longer_than_double, + reason="array repr problem") +@pytest.mark.skipif(string_to_longdouble_inaccurate, + reason="Need strtold_l") def test_array_repr(): o = 1 + LD_INFO.eps a = np.array([o]) diff --git a/numpy/core/tests/test_mem_overlap.py b/numpy/core/tests/test_mem_overlap.py index 92baa0896..076dc7c11 100644 --- a/numpy/core/tests/test_mem_overlap.py +++ b/numpy/core/tests/test_mem_overlap.py @@ -2,15 +2,17 @@ from __future__ import division, absolute_import, print_function import sys import itertools +import pytest import numpy as np -from numpy.testing import (run_module_suite, assert_, assert_raises, assert_equal, - assert_array_equal, assert_allclose, dec) - from numpy.core._multiarray_tests import solve_diophantine, internal_overlap from numpy.core import _umath_tests from numpy.lib.stride_tricks import as_strided from numpy.compat import long +from numpy.testing import ( + run_module_suite, assert_, assert_raises, assert_equal, assert_array_equal, + assert_allclose + ) if sys.version_info[0] >= 3: xrange = range @@ -97,7 +99,7 @@ def test_overlapping_assignments(): _check_assignment(srcidx, dstidx) -@dec.slow +@pytest.mark.slow def test_diophantine_fuzz(): # Fuzz test the diophantine solver rng = np.random.RandomState(1234) @@ -374,7 +376,7 @@ def check_may_share_memory_easy_fuzz(get_max_work, same_steps, min_count): infeasible += 1 -@dec.slow +@pytest.mark.slow def test_may_share_memory_easy_fuzz(): # Check that overlap problems with common strides are always # solved with little work. @@ -384,7 +386,7 @@ def test_may_share_memory_easy_fuzz(): min_count=2000) -@dec.slow +@pytest.mark.slow def test_may_share_memory_harder_fuzz(): # Overlap problems with not necessarily common strides take more # work. @@ -686,7 +688,7 @@ class TestUFunc(object): # Check result assert_copy_equivalent(operation, [a], out=b_out, axis=axis) - @dec.slow + @pytest.mark.slow def test_unary_ufunc_call_fuzz(self): self.check_unary_fuzz(np.invert, None, np.int16) @@ -897,7 +899,7 @@ class TestUFunc(object): check(x, x.copy(), x) check(x, x, x.copy()) - @dec.slow + @pytest.mark.slow def test_binary_ufunc_1d_manual(self): ufunc = np.add diff --git a/numpy/core/tests/test_memmap.py b/numpy/core/tests/test_memmap.py index c00867ce1..d6224ed02 100644 --- a/numpy/core/tests/test_memmap.py +++ b/numpy/core/tests/test_memmap.py @@ -3,8 +3,9 @@ from __future__ import division, absolute_import, print_function import sys import os import shutil -from tempfile import NamedTemporaryFile, TemporaryFile, mktemp, mkdtemp import mmap +import pytest +from tempfile import NamedTemporaryFile, TemporaryFile, mktemp, mkdtemp from numpy import ( memmap, sum, average, product, ndarray, isscalar, add, subtract, multiply) @@ -13,7 +14,7 @@ from numpy.compat import Path from numpy import arange, allclose, asarray from numpy.testing import ( run_module_suite, assert_, assert_equal, assert_array_equal, - dec, suppress_warnings + suppress_warnings ) class TestMemmap(object): @@ -76,7 +77,7 @@ class TestMemmap(object): del b del fp - @dec.skipif(Path is None, "No pathlib.Path") + @pytest.mark.skipif(Path is None, reason="No pathlib.Path") def test_path(self): tmpname = mktemp('', 'mmap', dir=self.tempdir) fp = memmap(Path(tmpname), dtype=self.dtype, mode='w+', @@ -94,7 +95,8 @@ class TestMemmap(object): shape=self.shape) assert_equal(fp.filename, self.tmpfp.name) - @dec.knownfailureif(sys.platform == 'gnu0', "This test is known to fail on hurd") + @pytest.mark.skipif(sys.platform == 'gnu0', + reason="Known to fail on hurd") def test_flush(self): fp = memmap(self.tmpfp, dtype=self.dtype, mode='w+', shape=self.shape) diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index d861da4b6..31d7bd2d0 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -17,6 +17,7 @@ import functools import ctypes import os import gc +import pytest from contextlib import contextmanager if sys.version_info[0] >= 3: import builtins @@ -31,7 +32,7 @@ from numpy.testing import ( run_module_suite, assert_, assert_raises, assert_warns, assert_equal, assert_almost_equal, assert_array_equal, assert_raises_regex, assert_array_almost_equal, assert_allclose, IS_PYPY, HAS_REFCOUNT, - assert_array_less, runstring, dec, SkipTest, temppath, suppress_warnings + assert_array_less, runstring, SkipTest, temppath, suppress_warnings ) from ._locales import CommaDecimalPointLocale @@ -726,7 +727,7 @@ class TestCreation(object): d = np.zeros(2, dtype='(2,4)i4, (2,4)i4') assert_equal(np.count_nonzero(d), 0) - @dec.slow + @pytest.mark.slow def test_zeros_big(self): # test big array as they might be allocated different by the system types = np.typecodes['AllInteger'] + np.typecodes['AllFloat'] @@ -797,7 +798,7 @@ class TestCreation(object): assert_equal(np.array([[1j, 1j],[1, 1]]).dtype, complex) assert_equal(np.array([[1, 1, 1],[1, 1j, 1.], [1, 1, 1]]).dtype, complex) - @dec.skipif(sys.version_info[0] >= 3) + @pytest.mark.skipif(sys.version_info[0] >= 3, reason="Not Python 2") def test_sequence_long(self): assert_equal(np.array([long(4), long(4)]).dtype, np.long) assert_equal(np.array([long(4), 2**80]).dtype, object) @@ -1216,7 +1217,7 @@ class TestBool(object): # covers most cases of the 16 byte unrolled code self.check_count_nonzero(12, 17) - @dec.slow + @pytest.mark.slow def test_count_nonzero_all(self): # check all combinations in a length 17 array # covers all cases of the 16 byte unrolled code @@ -1255,11 +1256,11 @@ class TestBool(object): def test_cast_from_void(self): self._test_cast_from_flexible(np.void) - @dec.knownfailureif(True, "See gh-9847") + @pytest.mark.xfail(reason="See gh-9847") def test_cast_from_unicode(self): self._test_cast_from_flexible(np.unicode_) - @dec.knownfailureif(True, "See gh-9847") + @pytest.mark.xfail(reason="See gh-9847") def test_cast_from_bytes(self): self._test_cast_from_flexible(np.bytes_) @@ -4385,7 +4386,7 @@ class TestIO(object): np.array([1, 2, 3, 4]), dtype='<f4') - @dec.slow # takes > 1 minute on mechanical hard drive + @pytest.mark.slow # takes > 1 minute on mechanical hard drive def test_big_binary(self): """Test workarounds for 32-bit limited fwrite, fseek, and ftell calls in windows. These normally would hang doing something like this. diff --git a/numpy/core/tests/test_nditer.py b/numpy/core/tests/test_nditer.py index 9d8f4f06a..50bcd4508 100644 --- a/numpy/core/tests/test_nditer.py +++ b/numpy/core/tests/test_nditer.py @@ -2,13 +2,14 @@ from __future__ import division, absolute_import, print_function import sys import warnings +import pytest import numpy as np import numpy.core._multiarray_tests as _multiarray_tests from numpy import array, arange, nditer, all from numpy.testing import ( run_module_suite, assert_, assert_equal, assert_array_equal, - assert_raises, assert_warns, dec, HAS_REFCOUNT, suppress_warnings + assert_raises, assert_warns, HAS_REFCOUNT, suppress_warnings ) @@ -33,7 +34,7 @@ def iter_iterindices(i): i.iternext() return ret -@dec._needs_refcount +@pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts") def test_iter_refcount(): # Make sure the iterator doesn't leak @@ -2082,7 +2083,7 @@ def test_iter_buffering_growinner(): assert_equal(i[0].size, a.size) -@dec.slow +@pytest.mark.slow def test_iter_buffered_reduce_reuse(): # large enough array for all views, including negative strides. a = np.arange(2*3**5)[3**5:3**5+1] diff --git a/numpy/core/tests/test_numeric.py b/numpy/core/tests/test_numeric.py index d7cdd77f1..52eebdd02 100644 --- a/numpy/core/tests/test_numeric.py +++ b/numpy/core/tests/test_numeric.py @@ -4,6 +4,7 @@ import sys import warnings import itertools import platform +import pytest from decimal import Decimal import numpy as np @@ -12,7 +13,7 @@ from numpy.random import rand, randint, randn from numpy.testing import ( run_module_suite, assert_, assert_equal, assert_raises, assert_raises_regex, assert_array_equal, assert_almost_equal, - assert_array_almost_equal, dec, suppress_warnings + assert_array_almost_equal, suppress_warnings, HAS_REFCOUNT ) @@ -467,7 +468,7 @@ class TestSeterr(object): np.seterr(**old) assert_(np.geterr() == old) - @dec.skipif(platform.machine() == "armv5tel", "See gh-413.") + @pytest.mark.skipif(platform.machine() == "armv5tel", reason="See gh-413.") def test_divide_err(self): with np.errstate(divide='raise'): try: @@ -551,7 +552,7 @@ class TestFloatExceptions(object): self.assert_raises_fpe(fpeerr, flop, sc1, sc2[()]) self.assert_raises_fpe(fpeerr, flop, sc1[()], sc2[()]) - @dec.knownfailureif(True, "See ticket #2350") + @pytest.mark.xfail(reason="See ticket #2350") def test_floating_exceptions(self): # Test basic arithmetic function errors with np.errstate(all='raise'): @@ -2092,7 +2093,7 @@ class TestCreationFuncs(object): self.check_function(np.full, 0) self.check_function(np.full, 1) - @dec._needs_refcount + @pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts") def test_for_reference_leak(self): # Make sure we have an object for reference dim = 1 diff --git a/numpy/core/tests/test_print.py b/numpy/core/tests/test_print.py index f432711a9..b8b2581f3 100644 --- a/numpy/core/tests/test_print.py +++ b/numpy/core/tests/test_print.py @@ -1,14 +1,11 @@ from __future__ import division, absolute_import, print_function import sys -import locale -import contextlib -import nose import numpy as np from numpy.testing import ( - run_module_suite, assert_, assert_equal, SkipTest, dec -) + run_module_suite, assert_, assert_equal, SkipTest + ) from ._locales import CommaDecimalPointLocale diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py index 119594668..ebc408b73 100644 --- a/numpy/core/tests/test_regression.py +++ b/numpy/core/tests/test_regression.py @@ -7,6 +7,7 @@ import platform import gc import warnings import tempfile +import pytest from os import path from io import BytesIO from itertools import chain @@ -15,7 +16,7 @@ import numpy as np from numpy.testing import ( run_module_suite, assert_, assert_equal, IS_PYPY, assert_almost_equal, assert_array_equal, assert_array_almost_equal, - assert_raises, assert_warns, dec, suppress_warnings, + assert_raises, assert_warns, suppress_warnings, _assert_valid_refcount, HAS_REFCOUNT, ) from numpy.compat import asbytes, asunicode, long @@ -600,7 +601,8 @@ class TestRegression(object): # Cannot test if NPY_RELAXED_STRIDES_CHECKING changes the strides. # With NPY_RELAXED_STRIDES_CHECKING the test becomes superfluous. - @dec.skipif(np.ones(1).strides[0] == np.iinfo(np.intp).max) + @pytest.mark.skipif(np.ones(1).strides[0] == np.iinfo(np.intp).max, + reason="Using relaxed stride checking") def test_reshape_trailing_ones_strides(self): # GitHub issue gh-2949, bad strides for trailing ones of new shape a = np.zeros(12, dtype=np.int32)[::2] # not contiguous @@ -859,7 +861,8 @@ class TestRegression(object): # Cannot test if NPY_RELAXED_STRIDES_CHECKING changes the strides. # With NPY_RELAXED_STRIDES_CHECKING the test becomes superfluous, # 0-sized reshape itself is tested elsewhere. - @dec.skipif(np.ones(1).strides[0] == np.iinfo(np.intp).max) + @pytest.mark.skipif(np.ones(1).strides[0] == np.iinfo(np.intp).max, + reason="Using relaxed stride checking") def test_copy_detection_corner_case2(self): # Ticket #771: strides are not set correctly when reshaping 0-sized # arrays @@ -1424,7 +1427,7 @@ class TestRegression(object): x[x.nonzero()] = x.ravel()[:1] assert_(x[0, 1] == x[0, 0]) - @dec._needs_refcount + @pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts") def test_structured_arrays_with_objects2(self): # Ticket #1299 second test stra = 'aaaa' @@ -1537,7 +1540,7 @@ class TestRegression(object): y = np.add(x, x, x) assert_equal(id(x), id(y)) - @dec._needs_refcount + @pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts") def test_take_refcount(self): # ticket #939 a = np.arange(16, dtype=float) @@ -1998,7 +2001,7 @@ class TestRegression(object): a = np.empty((100000000,), dtype='i1') del a - @dec._needs_refcount + @pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts") def test_ufunc_reduce_memoryleak(self): a = np.arange(6) acnt = sys.getrefcount(a) @@ -2228,7 +2231,7 @@ class TestRegression(object): assert_equal(uf(a), ()) assert_array_equal(a, [[3, 2, 1], [5, 4], [9, 7, 8, 6]]) - @dec._needs_refcount + @pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts") def test_leak_in_structured_dtype_comparison(self): # gh-6250 recordtype = np.dtype([('a', np.float64), diff --git a/numpy/core/tests/test_scalar_ctors.py b/numpy/core/tests/test_scalar_ctors.py index e2470779b..3ae5e025f 100644 --- a/numpy/core/tests/test_scalar_ctors.py +++ b/numpy/core/tests/test_scalar_ctors.py @@ -5,13 +5,13 @@ from __future__ import division, absolute_import, print_function import sys import platform -import numpy as np +import pytest +import numpy as np from numpy.testing import ( - run_module_suite, - assert_equal, assert_almost_equal, assert_raises, assert_warns, - dec -) + run_module_suite, assert_equal, assert_almost_equal, assert_raises, + assert_warns, + ) class TestFromString(object): def test_floating(self): @@ -43,11 +43,11 @@ class TestFromString(object): flongdouble = assert_warns(RuntimeWarning, np.longdouble, '-1e10000') assert_equal(flongdouble, -np.inf) - @dec.knownfailureif((sys.version_info[0] >= 3) or - (sys.platform == "win32" and - platform.architecture()[0] == "64bit"), - "numpy.intp('0xff', 16) not supported on Py3, " - "as it does not inherit from Python int") + @pytest.mark.skipif((sys.version_info[0] >= 3) + or (sys.platform == "win32" + and platform.architecture()[0] == "64bit"), + reason="numpy.intp('0xff', 16) not supported on Py3 " + "or 64 bit Windows") def test_intp(self): # Ticket #99 i_width = np.int_(0).nbytes*2 - 1 diff --git a/numpy/core/tests/test_scalarbuffer.py b/numpy/core/tests/test_scalarbuffer.py index cd887f2fb..0f7aea9bc 100644 --- a/numpy/core/tests/test_scalarbuffer.py +++ b/numpy/core/tests/test_scalarbuffer.py @@ -3,7 +3,9 @@ Test scalar buffer interface adheres to PEP 3118 """ import sys import numpy as np -from numpy.testing import run_module_suite, assert_, assert_equal, dec +import pytest + +from numpy.testing import run_module_suite, assert_, assert_equal # PEP3118 format strings for native (standard alignment and byteorder) types scalars_and_codes = [ @@ -28,11 +30,10 @@ scalars_and_codes = [ ] +@pytest.mark.skipif(sys.version_info.major < 3, + reason="Python 2 scalars lack a buffer interface") class TestScalarPEP3118(object): - skip_if_no_buffer_interface = dec.skipif(sys.version_info.major < 3, - "scalars do not implement buffer interface in Python 2") - @skip_if_no_buffer_interface def test_scalar_match_array(self): for scalar, _ in scalars_and_codes: x = scalar() @@ -41,7 +42,6 @@ class TestScalarPEP3118(object): mv_a = memoryview(a) assert_equal(mv_x.format, mv_a.format) - @skip_if_no_buffer_interface def test_scalar_dim(self): for scalar, _ in scalars_and_codes: x = scalar() @@ -52,14 +52,12 @@ class TestScalarPEP3118(object): assert_equal(mv_x.strides, ()) assert_equal(mv_x.suboffsets, ()) - @skip_if_no_buffer_interface def test_scalar_known_code(self): for scalar, code in scalars_and_codes: x = scalar() mv_x = memoryview(x) assert_equal(mv_x.format, code) - @skip_if_no_buffer_interface def test_void_scalar_structured_data(self): dt = np.dtype([('name', np.unicode_, 16), ('grades', np.float64, (2,))]) x = np.array(('ndarray_scalar', (1.2, 3.0)), dtype=dt)[()] diff --git a/numpy/core/tests/test_scalarmath.py b/numpy/core/tests/test_scalarmath.py index 7d0be9cf7..6d3ea02c5 100644 --- a/numpy/core/tests/test_scalarmath.py +++ b/numpy/core/tests/test_scalarmath.py @@ -5,13 +5,14 @@ import warnings import itertools import operator import platform +import pytest import numpy as np from numpy.testing import ( run_module_suite, assert_, assert_equal, assert_raises, assert_almost_equal, assert_allclose, assert_array_equal, - IS_PYPY, suppress_warnings, dec, _gen_alignment_data, assert_warns + IS_PYPY, suppress_warnings, _gen_alignment_data, assert_warns ) types = [np.bool_, np.byte, np.ubyte, np.short, np.ushort, np.intc, np.uintc, @@ -410,8 +411,7 @@ class TestConversion(object): assert_raises(OverflowError, int, x) assert_equal(len(sup.log), 1) - @dec.knownfailureif(not IS_PYPY, - "__int__ is not the same as int in cpython (gh-9972)") + @pytest.mark.skipif(not IS_PYPY, reason="Test is PyPy only (gh-9972)") def test_int_from_infinite_longdouble___int__(self): x = np.longdouble(np.inf) assert_raises(OverflowError, x.__int__) @@ -421,8 +421,10 @@ class TestConversion(object): assert_raises(OverflowError, x.__int__) assert_equal(len(sup.log), 1) - @dec.knownfailureif(platform.machine().startswith("ppc64")) - @dec.skipif(np.finfo(np.double) == np.finfo(np.longdouble)) + @pytest.mark.skipif(np.finfo(np.double) == np.finfo(np.longdouble), + reason="long double is same as double") + @pytest.mark.skipif(platform.machine().startswith("ppc64"), + reason="IBM double double") def test_int_from_huge_longdouble(self): # Produce a longdouble that would overflow a double, # use exponent that avoids bug in Darwin pow function. diff --git a/numpy/core/tests/test_umath.py b/numpy/core/tests/test_umath.py index fe7768e53..9dc9f5f08 100644 --- a/numpy/core/tests/test_umath.py +++ b/numpy/core/tests/test_umath.py @@ -5,6 +5,7 @@ import platform import warnings import fnmatch import itertools +import pytest import numpy.core.umath as ncu from numpy.core import _umath_tests as ncu_tests @@ -12,7 +13,7 @@ import numpy as np from numpy.testing import ( run_module_suite, assert_, assert_equal, assert_raises, assert_raises_regex, assert_array_equal, assert_almost_equal, - assert_array_almost_equal, dec, assert_allclose, assert_no_warnings, + assert_array_almost_equal, assert_allclose, assert_no_warnings, suppress_warnings, _gen_alignment_data, ) @@ -2491,7 +2492,8 @@ class TestComplexFunctions(object): for dtype in [np.complex64, np.complex_]: self.check_loss_of_precision(dtype) - @dec.knownfailureif(is_longdouble_finfo_bogus(), "Bogus long double finfo") + @pytest.mark.skipif(is_longdouble_finfo_bogus(), + reason="Bogus long double finfo") def test_loss_of_precision_longcomplex(self): self.check_loss_of_precision(np.longcomplex) @@ -2611,14 +2613,19 @@ def _test_nextafter(t): def test_nextafter(): return _test_nextafter(np.float64) + def test_nextafterf(): return _test_nextafter(np.float32) -@dec.knownfailureif(sys.platform == 'win32', - "Long double support buggy on win32, ticket 1664.") + +@pytest.mark.skipif(np.finfo(np.double) == np.finfo(np.longdouble), + reason="long double is same as double") +@pytest.mark.skipif(platform.machine().startswith("ppc64"), + reason="IBM double double") def test_nextafterl(): return _test_nextafter(np.longdouble) + def test_nextafter_0(): for t, direction in itertools.product(np.sctypes['float'], (1, -1)): tiny = np.finfo(t).tiny @@ -2643,8 +2650,11 @@ def test_spacing(): def test_spacingf(): return _test_spacing(np.float32) -@dec.knownfailureif(sys.platform == 'win32', - "Long double support buggy on win32, ticket 1664.") + +@pytest.mark.skipif(np.finfo(np.double) == np.finfo(np.longdouble), + reason="long double is same as double") +@pytest.mark.skipif(platform.machine().startswith("ppc64"), + reason="IBM double double") def test_spacingl(): return _test_spacing(np.longdouble) diff --git a/numpy/core/tests/test_umath_complex.py b/numpy/core/tests/test_umath_complex.py index 1b098a120..c5ab1b229 100644 --- a/numpy/core/tests/test_umath_complex.py +++ b/numpy/core/tests/test_umath_complex.py @@ -2,12 +2,13 @@ from __future__ import division, absolute_import, print_function import sys import platform +import pytest import numpy as np import numpy.core.umath as ncu from numpy.testing import ( run_module_suite, assert_raises, assert_equal, assert_array_equal, - assert_almost_equal, dec + assert_almost_equal ) # TODO: branch cuts (use Pauli code) @@ -17,17 +18,17 @@ from numpy.testing import ( # At least on Windows the results of many complex functions are not conforming # to the C99 standard. See ticket 1574. # Ditto for Solaris (ticket 1642) and OS X on PowerPC. +#FIXME: this will probably change when we require full C99 campatibility with np.errstate(all='ignore'): functions_seem_flaky = ((np.exp(complex(np.inf, 0)).imag != 0) or (np.log(complex(np.NZERO, 0)).imag != np.pi)) # TODO: replace with a check on whether platform-provided C99 funcs are used -skip_complex_tests = (not sys.platform.startswith('linux') or functions_seem_flaky) +xfail_complex_tests = (not sys.platform.startswith('linux') or functions_seem_flaky) + +# TODO This can be xfail when the generator functions are got rid of. +platform_skip = pytest.mark.skipif(xfail_complex_tests, + reason="Inadequate C99 complex support") -def platform_skip(func): - return dec.skipif(skip_complex_tests, - "Numpy is using complex functions (e.g. sqrt) provided by your" - "platform's C library. However, they do not seem to behave according" - "to C99 -- so C99 tests are skipped.")(func) class TestCexp(object): @@ -120,14 +121,15 @@ class TestCexp(object): # cexp(nan + nani) is nan + nani yield check, f, np.nan, np.nan, np.nan, np.nan - @dec.knownfailureif(True, "cexp(nan + 0I) is wrong on most implementations") + # TODO This can be xfail when the generator functions are got rid of. + @pytest.mark.skip(reason="cexp(nan + 0I) is wrong on most platforms") def test_special_values2(self): # XXX: most implementations get it wrong here (including glibc <= 2.10) # cexp(nan + 0i) is nan + 0i check = check_complex_value f = np.exp - yield check, f, np.nan, 0, np.nan, 0 + check(f, np.nan, 0, np.nan, 0) class TestClog(object): def test_simple(self): @@ -138,7 +140,7 @@ class TestClog(object): assert_almost_equal(y[i], y_r[i]) @platform_skip - @dec.skipif(platform.machine() == "armv5tel", "See gh-413.") + @pytest.mark.skipif(platform.machine() == "armv5tel", reason="See gh-413.") def test_special_values(self): xl = [] yl = [] @@ -460,32 +462,33 @@ class TestCarg(object): check_real_value(ncu._arg, 1, 1, 0.25*np.pi, False) check_real_value(ncu._arg, np.PZERO, np.PZERO, np.PZERO) - @dec.knownfailureif(True, - "Complex arithmetic with signed zero is buggy on most implementation") + # TODO This can be xfail when the generator functions are got rid of. + @pytest.mark.skip( + reason="Complex arithmetic with signed zero fails on most platforms") def test_zero(self): # carg(-0 +- 0i) returns +- pi - yield check_real_value, ncu._arg, np.NZERO, np.PZERO, np.pi, False - yield check_real_value, ncu._arg, np.NZERO, np.NZERO, -np.pi, False + check_real_value(ncu._arg, np.NZERO, np.PZERO, np.pi, False) + check_real_value(ncu._arg, np.NZERO, np.NZERO, -np.pi, False) # carg(+0 +- 0i) returns +- 0 - yield check_real_value, ncu._arg, np.PZERO, np.PZERO, np.PZERO - yield check_real_value, ncu._arg, np.PZERO, np.NZERO, np.NZERO + check_real_value(ncu._arg, np.PZERO, np.PZERO, np.PZERO) + check_real_value(ncu._arg, np.PZERO, np.NZERO, np.NZERO) # carg(x +- 0i) returns +- 0 for x > 0 - yield check_real_value, ncu._arg, 1, np.PZERO, np.PZERO, False - yield check_real_value, ncu._arg, 1, np.NZERO, np.NZERO, False + check_real_value(ncu._arg, 1, np.PZERO, np.PZERO, False) + check_real_value(ncu._arg, 1, np.NZERO, np.NZERO, False) # carg(x +- 0i) returns +- pi for x < 0 - yield check_real_value, ncu._arg, -1, np.PZERO, np.pi, False - yield check_real_value, ncu._arg, -1, np.NZERO, -np.pi, False + check_real_value(ncu._arg, -1, np.PZERO, np.pi, False) + check_real_value(ncu._arg, -1, np.NZERO, -np.pi, False) # carg(+- 0 + yi) returns pi/2 for y > 0 - yield check_real_value, ncu._arg, np.PZERO, 1, 0.5 * np.pi, False - yield check_real_value, ncu._arg, np.NZERO, 1, 0.5 * np.pi, False + check_real_value(ncu._arg, np.PZERO, 1, 0.5 * np.pi, False) + check_real_value(ncu._arg, np.NZERO, 1, 0.5 * np.pi, False) # carg(+- 0 + yi) returns -pi/2 for y < 0 - yield check_real_value, ncu._arg, np.PZERO, -1, 0.5 * np.pi, False - yield check_real_value, ncu._arg, np.NZERO, -1, -0.5 * np.pi, False + check_real_value(ncu._arg, np.PZERO, -1, 0.5 * np.pi, False) + check_real_value(ncu._arg, np.NZERO, -1, -0.5 * np.pi, False) #def test_branch_cuts(self): # _check_branch_cut(ncu._arg, -1, 1j, -1, 1) diff --git a/numpy/distutils/__init__.py b/numpy/distutils/__init__.py index d5921b399..b794bebd7 100644 --- a/numpy/distutils/__init__.py +++ b/numpy/distutils/__init__.py @@ -17,8 +17,9 @@ try: # Normally numpy is installed if the above import works, but an interrupted # in-place build could also have left a __config__.py. In that case the # next import may still fail, so keep it inside the try block. - from numpy.testing import _numpy_tester - test = _numpy_tester().test + from numpy.testing._private.pytesttester import PytestTester + test = PytestTester(__name__) + del PytestTester except ImportError: pass diff --git a/numpy/distutils/tests/test_system_info.py b/numpy/distutils/tests/test_system_info.py index c6a9b9915..bec606c44 100644 --- a/numpy/distutils/tests/test_system_info.py +++ b/numpy/distutils/tests/test_system_info.py @@ -2,13 +2,14 @@ from __future__ import division, print_function import os import shutil +import pytest from tempfile import mkstemp, mkdtemp from subprocess import Popen, PIPE from distutils.errors import DistutilsError from numpy.distutils import ccompiler, customized_ccompiler from numpy.testing import ( - run_module_suite, assert_, assert_equal, dec + run_module_suite, assert_, assert_equal ) from numpy.distutils.system_info import system_info, ConfigParser from numpy.distutils.system_info import default_lib_dirs, default_include_dirs @@ -201,7 +202,7 @@ class TestSystemInfoReading(object): extra = tsi.calc_extra_info() assert_equal(extra['extra_link_args'], ['-Wl,-rpath=' + self._lib2]) - @dec.skipif(not HAVE_COMPILER) + @pytest.mark.skipif(not HAVE_COMPILER, reason="Missing compiler") def test_compile1(self): # Compile source and link the first source c = customized_ccompiler() @@ -216,8 +217,9 @@ class TestSystemInfoReading(object): finally: os.chdir(previousDir) - @dec.skipif(not HAVE_COMPILER) - @dec.skipif('msvc' in repr(ccompiler.new_compiler())) + @pytest.mark.skipif(not HAVE_COMPILER, reason="Missing compiler") + @pytest.mark.skipif('msvc' in repr(ccompiler.new_compiler()), + reason="Fails with MSVC compiler ") def test_compile2(self): # Compile source and link the second source tsi = self.c_temp2 diff --git a/numpy/f2py/__init__.py b/numpy/f2py/__init__.py index 86cc45b42..5075c682d 100644 --- a/numpy/f2py/__init__.py +++ b/numpy/f2py/__init__.py @@ -69,5 +69,6 @@ def compile(source, f.close() return status -from numpy.testing import _numpy_tester -test = _numpy_tester().test +from numpy.testing._private.pytesttester import PytestTester +test = PytestTester(__name__) +del PytestTester diff --git a/numpy/f2py/tests/test_assumed_shape.py b/numpy/f2py/tests/test_assumed_shape.py index 371aab755..b6fde20e4 100644 --- a/numpy/f2py/tests/test_assumed_shape.py +++ b/numpy/f2py/tests/test_assumed_shape.py @@ -1,8 +1,9 @@ from __future__ import division, absolute_import, print_function import os +import pytest -from numpy.testing import run_module_suite, assert_, dec +from numpy.testing import run_module_suite, assert_ from . import util @@ -17,7 +18,7 @@ class TestAssumedShapeSumExample(util.F2PyTest): _path('src', 'assumed_shape', 'foo_mod.f90'), ] - @dec.slow + @pytest.mark.slow def test_all(self): r = self.module.fsum([1, 2]) assert_(r == 3, repr(r)) diff --git a/numpy/f2py/tests/test_block_docstring.py b/numpy/f2py/tests/test_block_docstring.py index eb11201ef..c820895c5 100644 --- a/numpy/f2py/tests/test_block_docstring.py +++ b/numpy/f2py/tests/test_block_docstring.py @@ -2,21 +2,23 @@ from __future__ import division, absolute_import, print_function import textwrap import sys +import pytest from . import util -from numpy.testing import run_module_suite, assert_equal, dec +from numpy.testing import run_module_suite, assert_equal class TestBlockDocString(util.F2PyTest): code = """ SUBROUTINE FOO() INTEGER BAR(2, 3) - + COMMON /BLOCK/ BAR RETURN END """ - @dec.knownfailureif(sys.platform=='win32', msg='Fails with MinGW64 Gfortran (Issue #9673)') + @pytest.mark.skipif(sys.platform=='win32', + reason='Fails with MinGW64 Gfortran (Issue #9673)') def test_block_docstring(self): expected = "'i'-array(2,3)\n" assert_equal(self.module.block.__doc__, expected) diff --git a/numpy/f2py/tests/test_callback.py b/numpy/f2py/tests/test_callback.py index 1b9a582ed..19aa4dd6e 100644 --- a/numpy/f2py/tests/test_callback.py +++ b/numpy/f2py/tests/test_callback.py @@ -3,9 +3,10 @@ from __future__ import division, absolute_import, print_function import math import textwrap import sys +import pytest import numpy as np -from numpy.testing import run_module_suite, assert_, assert_equal, dec +from numpy.testing import run_module_suite, assert_, assert_equal from . import util @@ -60,12 +61,12 @@ cf2py intent(out) a end """ - @dec.slow + @pytest.mark.slow def test_all(self): for name in "t,t2".split(","): self.check_function(name) - @dec.slow + @pytest.mark.slow def test_docstring(self): expected = """ a = t(fun,[fun_extra_args]) @@ -130,8 +131,8 @@ cf2py intent(out) a r = t(a.mth) assert_(r == 9, repr(r)) - @dec.knownfailureif(sys.platform=='win32', - msg='Fails with MinGW64 Gfortran (Issue #9673)') + @pytest.mark.skipif(sys.platform=='win32', + reason='Fails with MinGW64 Gfortran (Issue #9673)') def test_string_callback(self): def callback(code): @@ -144,8 +145,8 @@ cf2py intent(out) a r = f(callback) assert_(r == 0, repr(r)) - @dec.knownfailureif(sys.platform=='win32', - msg='Fails with MinGW64 Gfortran (Issue #9673)') + @pytest.mark.skipif(sys.platform=='win32', + reason='Fails with MinGW64 Gfortran (Issue #9673)') def test_string_callback_array(self): # See gh-10027 cu = np.zeros((1, 8), 'S1') diff --git a/numpy/f2py/tests/test_common.py b/numpy/f2py/tests/test_common.py index 81082e575..30640f8e9 100644 --- a/numpy/f2py/tests/test_common.py +++ b/numpy/f2py/tests/test_common.py @@ -2,10 +2,12 @@ from __future__ import division, absolute_import, print_function import os import sys +import pytest + import numpy as np from . import util -from numpy.testing import run_module_suite, assert_array_equal, dec +from numpy.testing import run_module_suite, assert_array_equal def _path(*a): return os.path.join(*((os.path.dirname(__file__),) + a)) @@ -13,7 +15,8 @@ def _path(*a): class TestCommonBlock(util.F2PyTest): sources = [_path('src', 'common', 'block.f')] - @dec.knownfailureif(sys.platform=='win32', msg='Fails with MinGW64 Gfortran (Issue #9673)') + @pytest.mark.skipif(sys.platform=='win32', + reason='Fails with MinGW64 Gfortran (Issue #9673)') def test_common_block(self): self.module.initcb() assert_array_equal(self.module.block.long_bn, diff --git a/numpy/f2py/tests/test_kind.py b/numpy/f2py/tests/test_kind.py index 7cfe2e977..61c39a092 100644 --- a/numpy/f2py/tests/test_kind.py +++ b/numpy/f2py/tests/test_kind.py @@ -1,8 +1,9 @@ from __future__ import division, absolute_import, print_function import os +import pytest -from numpy.testing import run_module_suite, assert_, dec +from numpy.testing import run_module_suite, assert_ from numpy.f2py.crackfortran import ( _selected_int_kind_func as selected_int_kind, _selected_real_kind_func as selected_real_kind @@ -17,7 +18,7 @@ def _path(*a): class TestKind(util.F2PyTest): sources = [_path('src', 'kind', 'foo.f90')] - @dec.slow + @pytest.mark.slow def test_all(self): selectedrealkind = self.module.selectedrealkind selectedintkind = self.module.selectedintkind diff --git a/numpy/f2py/tests/test_mixed.py b/numpy/f2py/tests/test_mixed.py index c145a4b23..e6eea8c4f 100644 --- a/numpy/f2py/tests/test_mixed.py +++ b/numpy/f2py/tests/test_mixed.py @@ -2,8 +2,9 @@ from __future__ import division, absolute_import, print_function import os import textwrap +import pytest -from numpy.testing import run_module_suite, assert_, assert_equal, dec +from numpy.testing import run_module_suite, assert_, assert_equal from . import util @@ -16,13 +17,13 @@ class TestMixed(util.F2PyTest): _path('src', 'mixed', 'foo_fixed.f90'), _path('src', 'mixed', 'foo_free.f90')] - @dec.slow + @pytest.mark.slow def test_all(self): assert_(self.module.bar11() == 11) assert_(self.module.foo_fixed.bar12() == 12) assert_(self.module.foo_free.bar13() == 13) - @dec.slow + @pytest.mark.slow def test_docstring(self): expected = """ a = bar11() diff --git a/numpy/f2py/tests/test_parameter.py b/numpy/f2py/tests/test_parameter.py index 285b693a1..11132475e 100644 --- a/numpy/f2py/tests/test_parameter.py +++ b/numpy/f2py/tests/test_parameter.py @@ -2,9 +2,10 @@ from __future__ import division, absolute_import, print_function import os import math +import pytest import numpy as np -from numpy.testing import run_module_suite, dec, assert_raises, assert_equal +from numpy.testing import run_module_suite, assert_raises, assert_equal from . import util @@ -22,7 +23,7 @@ class TestParameters(util.F2PyTest): _path('src', 'parameter', 'constant_non_compound.f90'), ] - @dec.slow + @pytest.mark.slow def test_constant_real_single(self): # non-contiguous should raise error x = np.arange(6, dtype=np.float32)[::2] @@ -33,7 +34,7 @@ class TestParameters(util.F2PyTest): self.module.foo_single(x) assert_equal(x, [0 + 1 + 2*3, 1, 2]) - @dec.slow + @pytest.mark.slow def test_constant_real_double(self): # non-contiguous should raise error x = np.arange(6, dtype=np.float64)[::2] @@ -44,7 +45,7 @@ class TestParameters(util.F2PyTest): self.module.foo_double(x) assert_equal(x, [0 + 1 + 2*3, 1, 2]) - @dec.slow + @pytest.mark.slow def test_constant_compound_int(self): # non-contiguous should raise error x = np.arange(6, dtype=np.int32)[::2] @@ -55,14 +56,14 @@ class TestParameters(util.F2PyTest): self.module.foo_compound_int(x) assert_equal(x, [0 + 1 + 2*6, 1, 2]) - @dec.slow + @pytest.mark.slow def test_constant_non_compound_int(self): # check values x = np.arange(4, dtype=np.int32) self.module.foo_non_compound_int(x) assert_equal(x, [0 + 1 + 2 + 3*4, 1, 2, 3]) - @dec.slow + @pytest.mark.slow def test_constant_integer_int(self): # non-contiguous should raise error x = np.arange(6, dtype=np.int32)[::2] @@ -73,7 +74,7 @@ class TestParameters(util.F2PyTest): self.module.foo_int(x) assert_equal(x, [0 + 1 + 2*3, 1, 2]) - @dec.slow + @pytest.mark.slow def test_constant_integer_long(self): # non-contiguous should raise error x = np.arange(6, dtype=np.int64)[::2] @@ -84,7 +85,7 @@ class TestParameters(util.F2PyTest): self.module.foo_long(x) assert_equal(x, [0 + 1 + 2*3, 1, 2]) - @dec.slow + @pytest.mark.slow def test_constant_both(self): # non-contiguous should raise error x = np.arange(6, dtype=np.float64)[::2] @@ -95,7 +96,7 @@ class TestParameters(util.F2PyTest): self.module.foo(x) assert_equal(x, [0 + 1*3*3 + 2*3*3, 1*3, 2*3]) - @dec.slow + @pytest.mark.slow def test_constant_no(self): # non-contiguous should raise error x = np.arange(6, dtype=np.float64)[::2] @@ -106,7 +107,7 @@ class TestParameters(util.F2PyTest): self.module.foo_no(x) assert_equal(x, [0 + 1*3*3 + 2*3*3, 1*3, 2*3]) - @dec.slow + @pytest.mark.slow def test_constant_sum(self): # non-contiguous should raise error x = np.arange(6, dtype=np.float64)[::2] diff --git a/numpy/f2py/tests/test_quoted_character.py b/numpy/f2py/tests/test_quoted_character.py index 4770c11c4..748a17a38 100644 --- a/numpy/f2py/tests/test_quoted_character.py +++ b/numpy/f2py/tests/test_quoted_character.py @@ -1,16 +1,16 @@ from __future__ import division, absolute_import, print_function -from . import util - -from numpy.testing import run_module_suite, assert_equal, dec - import sys +import pytest + +from numpy.testing import run_module_suite, assert_equal +from . import util class TestQuotedCharacter(util.F2PyTest): code = """ SUBROUTINE FOO(OUT1, OUT2, OUT3, OUT4, OUT5, OUT6) CHARACTER SINGLE, DOUBLE, SEMICOL, EXCLA, OPENPAR, CLOSEPAR - PARAMETER (SINGLE="'", DOUBLE='"', SEMICOL=';', EXCLA="!", + PARAMETER (SINGLE="'", DOUBLE='"', SEMICOL=';', EXCLA="!", 1 OPENPAR="(", CLOSEPAR=")") CHARACTER OUT1, OUT2, OUT3, OUT4, OUT5, OUT6 Cf2py intent(out) OUT1, OUT2, OUT3, OUT4, OUT5, OUT6 @@ -24,7 +24,8 @@ Cf2py intent(out) OUT1, OUT2, OUT3, OUT4, OUT5, OUT6 END """ - @dec.knownfailureif(sys.platform=='win32', msg='Fails with MinGW64 Gfortran (Issue #9673)') + @pytest.mark.skipif(sys.platform=='win32', + reason='Fails with MinGW64 Gfortran (Issue #9673)') def test_quoted_character(self): assert_equal(self.module.foo(), (b"'", b'"', b';', b'!', b'(', b')')) diff --git a/numpy/f2py/tests/test_regression.py b/numpy/f2py/tests/test_regression.py index c34a5781c..a70d2c93f 100644 --- a/numpy/f2py/tests/test_regression.py +++ b/numpy/f2py/tests/test_regression.py @@ -2,9 +2,10 @@ from __future__ import division, absolute_import, print_function import os import math +import pytest import numpy as np -from numpy.testing import run_module_suite, dec, assert_raises, assert_equal +from numpy.testing import run_module_suite, assert_raises, assert_equal from . import util @@ -17,7 +18,7 @@ class TestIntentInOut(util.F2PyTest): # Check that intent(in out) translates as intent(inout) sources = [_path('src', 'regression', 'inout.f90')] - @dec.slow + @pytest.mark.slow def test_inout(self): # non-contiguous should raise error x = np.arange(6, dtype=np.float32)[::2] diff --git a/numpy/f2py/tests/test_return_character.py b/numpy/f2py/tests/test_return_character.py index 217b2c9dd..ec2d02658 100644 --- a/numpy/f2py/tests/test_return_character.py +++ b/numpy/f2py/tests/test_return_character.py @@ -1,7 +1,9 @@ from __future__ import division, absolute_import, print_function +import pytest + from numpy import array -from numpy.testing import run_module_suite, assert_, dec +from numpy.testing import run_module_suite, assert_ from . import util @@ -79,7 +81,7 @@ cf2py intent(out) ts end """ - @dec.slow + @pytest.mark.slow def test_all(self): for name in "t0,t1,t5,s0,s1,s5,ss".split(","): self.check_function(getattr(self.module, name)) @@ -138,7 +140,7 @@ module f90_return_char end module f90_return_char """ - @dec.slow + @pytest.mark.slow def test_all(self): for name in "t0,t1,t5,ts,s0,s1,s5,ss".split(","): self.check_function(getattr(self.module.f90_return_char, name)) diff --git a/numpy/f2py/tests/test_return_complex.py b/numpy/f2py/tests/test_return_complex.py index 73ced8ed8..72c00afeb 100644 --- a/numpy/f2py/tests/test_return_complex.py +++ b/numpy/f2py/tests/test_return_complex.py @@ -1,8 +1,10 @@ from __future__ import division, absolute_import, print_function +import pytest + from numpy import array from numpy.compat import long -from numpy.testing import run_module_suite, assert_, assert_raises, dec +from numpy.testing import run_module_suite, assert_, assert_raises from . import util @@ -102,7 +104,7 @@ cf2py intent(out) td end """ - @dec.slow + @pytest.mark.slow def test_all(self): for name in "t0,t8,t16,td,s0,s8,s16,sd".split(","): self.check_function(getattr(self.module, name)) @@ -161,7 +163,7 @@ module f90_return_complex end module f90_return_complex """ - @dec.slow + @pytest.mark.slow def test_all(self): for name in "t0,t8,t16,td,s0,s8,s16,sd".split(","): self.check_function(getattr(self.module.f90_return_complex, name)) diff --git a/numpy/f2py/tests/test_return_integer.py b/numpy/f2py/tests/test_return_integer.py index df8fc7c97..befc515a2 100644 --- a/numpy/f2py/tests/test_return_integer.py +++ b/numpy/f2py/tests/test_return_integer.py @@ -1,8 +1,10 @@ from __future__ import division, absolute_import, print_function +import pytest + from numpy import array from numpy.compat import long -from numpy.testing import run_module_suite, assert_, assert_raises, dec +from numpy.testing import run_module_suite, assert_, assert_raises from . import util @@ -101,7 +103,7 @@ cf2py intent(out) t8 end """ - @dec.slow + @pytest.mark.slow def test_all(self): for name in "t0,t1,t2,t4,t8,s0,s1,s2,s4,s8".split(","): self.check_function(getattr(self.module, name)) @@ -171,7 +173,7 @@ module f90_return_integer end module f90_return_integer """ - @dec.slow + @pytest.mark.slow def test_all(self): for name in "t0,t1,t2,t4,t8,s0,s1,s2,s4,s8".split(","): self.check_function(getattr(self.module.f90_return_integer, name)) diff --git a/numpy/f2py/tests/test_return_logical.py b/numpy/f2py/tests/test_return_logical.py index 221dc3cbd..917cc3f60 100644 --- a/numpy/f2py/tests/test_return_logical.py +++ b/numpy/f2py/tests/test_return_logical.py @@ -1,8 +1,10 @@ from __future__ import division, absolute_import, print_function +import pytest + from numpy import array from numpy.compat import long -from numpy.testing import run_module_suite, assert_, assert_raises, dec +from numpy.testing import run_module_suite, assert_, assert_raises from . import util @@ -110,7 +112,7 @@ c t8 = value c end """ - @dec.slow + @pytest.mark.slow def test_all(self): for name in "t0,t1,t2,t4,s0,s1,s2,s4".split(","): self.check_function(getattr(self.module, name)) @@ -180,7 +182,7 @@ module f90_return_logical end module f90_return_logical """ - @dec.slow + @pytest.mark.slow def test_all(self): for name in "t0,t1,t2,t4,t8,s0,s1,s2,s4,s8".split(","): self.check_function(getattr(self.module.f90_return_logical, name)) diff --git a/numpy/f2py/tests/test_return_real.py b/numpy/f2py/tests/test_return_real.py index a81549083..addbdcf49 100644 --- a/numpy/f2py/tests/test_return_real.py +++ b/numpy/f2py/tests/test_return_real.py @@ -1,8 +1,10 @@ from __future__ import division, absolute_import, print_function +import pytest + from numpy import array from numpy.compat import long -from numpy.testing import run_module_suite, assert_, assert_raises, dec +from numpy.testing import run_module_suite, assert_, assert_raises from . import util @@ -82,7 +84,7 @@ end interface end python module c_ext_return_real """ - @dec.slow + @pytest.mark.slow def test_all(self): for name in "t4,t8,s4,s8".split(","): self.check_function(getattr(self.module, name)) @@ -137,7 +139,7 @@ cf2py intent(out) td end """ - @dec.slow + @pytest.mark.slow def test_all(self): for name in "t0,t4,t8,td,s0,s4,s8,sd".split(","): self.check_function(getattr(self.module, name)) @@ -196,7 +198,7 @@ module f90_return_real end module f90_return_real """ - @dec.slow + @pytest.mark.slow def test_all(self): for name in "t0,t4,t8,td,s0,s4,s8,sd".split(","): self.check_function(getattr(self.module.f90_return_real, name)) diff --git a/numpy/f2py/tests/test_size.py b/numpy/f2py/tests/test_size.py index 1fcad05a5..59de9a64e 100644 --- a/numpy/f2py/tests/test_size.py +++ b/numpy/f2py/tests/test_size.py @@ -1,8 +1,9 @@ from __future__ import division, absolute_import, print_function import os +import pytest -from numpy.testing import run_module_suite, assert_equal, dec +from numpy.testing import run_module_suite, assert_equal from . import util @@ -13,7 +14,7 @@ def _path(*a): class TestSizeSumExample(util.F2PyTest): sources = [_path('src', 'size', 'foo.f90')] - @dec.slow + @pytest.mark.slow def test_all(self): r = self.module.foo([[]]) assert_equal(r, [0], repr(r)) @@ -27,7 +28,7 @@ class TestSizeSumExample(util.F2PyTest): r = self.module.foo([[1, 2], [3, 4], [5, 6]]) assert_equal(r, [3, 7, 11], repr(r)) - @dec.slow + @pytest.mark.slow def test_transpose(self): r = self.module.trans([[]]) assert_equal(r.T, [[]], repr(r)) @@ -38,7 +39,7 @@ class TestSizeSumExample(util.F2PyTest): r = self.module.trans([[1, 2, 3], [4, 5, 6]]) assert_equal(r, [[1, 4], [2, 5], [3, 6]], repr(r)) - @dec.slow + @pytest.mark.slow def test_flatten(self): r = self.module.flatten([[]]) assert_equal(r, [], repr(r)) diff --git a/numpy/f2py/tests/test_string.py b/numpy/f2py/tests/test_string.py index 065861c0b..79eeca1e9 100644 --- a/numpy/f2py/tests/test_string.py +++ b/numpy/f2py/tests/test_string.py @@ -1,8 +1,9 @@ from __future__ import division, absolute_import, print_function import os +import pytest -from numpy.testing import run_module_suite, assert_array_equal, dec +from numpy.testing import run_module_suite, assert_array_equal import numpy as np from . import util @@ -13,7 +14,7 @@ def _path(*a): class TestString(util.F2PyTest): sources = [_path('src', 'string', 'char.f90')] - @dec.slow + @pytest.mark.slow def test_char(self): strings = np.array(['ab', 'cd', 'ef'], dtype='c').T inp, out = self.module.char_test.change_strings(strings, strings.shape[1]) diff --git a/numpy/f2py/tests/util.py b/numpy/f2py/tests/util.py index 881b32810..466fd4970 100644 --- a/numpy/f2py/tests/util.py +++ b/numpy/f2py/tests/util.py @@ -16,10 +16,11 @@ import atexit import textwrap import re import random +import pytest import numpy.f2py from numpy.compat import asbytes, asstr -from numpy.testing import SkipTest, temppath, dec +from numpy.testing import SkipTest, temppath from importlib import import_module try: @@ -319,8 +320,10 @@ class F2PyTest(object): module = None module_name = None - @dec.knownfailureif(sys.platform=='win32', msg='Fails with MinGW64 Gfortran (Issue #9673)') def setup(self): + if sys.platform == 'win32': + raise SkipTest('Fails with MinGW64 Gfortran (Issue #9673)') + if self.module is not None: return diff --git a/numpy/fft/__init__.py b/numpy/fft/__init__.py index d1716bd4b..bbb6ec8c7 100644 --- a/numpy/fft/__init__.py +++ b/numpy/fft/__init__.py @@ -6,5 +6,6 @@ from .info import __doc__ from .fftpack import * from .helper import * -from numpy.testing import _numpy_tester -test = _numpy_tester().test +from numpy.testing._private.pytesttester import PytestTester +test = PytestTester(__name__) +del PytestTester diff --git a/numpy/lib/__init__.py b/numpy/lib/__init__.py index 0c2e6dfab..d764cdc7e 100644 --- a/numpy/lib/__init__.py +++ b/numpy/lib/__init__.py @@ -46,5 +46,6 @@ __all__ += financial.__all__ __all__ += nanfunctions.__all__ __all__ += histograms.__all__ -from numpy.testing import _numpy_tester -test = _numpy_tester().test +from numpy.testing._private.pytesttester import PytestTester +test = PytestTester(__name__) +del PytestTester diff --git a/numpy/lib/tests/test_format.py b/numpy/lib/tests/test_format.py index d3bd2cef7..127f57605 100644 --- a/numpy/lib/tests/test_format.py +++ b/numpy/lib/tests/test_format.py @@ -1,5 +1,6 @@ from __future__ import division, absolute_import, print_function +# doctest r''' Test the .npy file format. Set up: @@ -275,18 +276,18 @@ Test the header writing. "v\x00{'descr': [('x', '>i4', (2,)), ('y', '>f8', (2, 2)), ('z', '|u1')],\n 'fortran_order': False,\n 'shape': (2,)} \n" "\x16\x02{'descr': [('x', '>i4', (2,)),\n ('Info',\n [('value', '>c16'),\n ('y2', '>f8'),\n ('Info2',\n [('name', '|S2'),\n ('value', '>c16', (2,)),\n ('y3', '>f8', (2,)),\n ('z3', '>u4', (2,))]),\n ('name', '|S2'),\n ('z2', '|b1')]),\n ('color', '|S2'),\n ('info', [('Name', '>U8'), ('Value', '>c16')]),\n ('y', '>f8', (2, 2)),\n ('z', '|u1')],\n 'fortran_order': False,\n 'shape': (2,)} \n" ''' - import sys import os import shutil import tempfile import warnings +import pytest from io import BytesIO import numpy as np from numpy.testing import ( run_module_suite, assert_, assert_array_equal, assert_raises, raises, - dec, SkipTest + SkipTest ) from numpy.lib import format @@ -477,7 +478,7 @@ def test_long_str(): assert_array_equal(long_str_arr, long_str_arr2) -@dec.slow +@pytest.mark.slow def test_memmap_roundtrip(): # Fixme: test crashes nose on windows. if not (sys.platform == 'win32' or sys.platform == 'cygwin'): @@ -628,7 +629,7 @@ def test_version_2_0(): assert_raises(ValueError, format.write_array, f, d, (1, 0)) -@dec.slow +@pytest.mark.slow def test_version_2_0_memmap(): # requires more than 2 byte for header dt = [(("%d" % i) * 100, float) for i in range(500)] @@ -832,8 +833,9 @@ def test_large_file_support(): assert_array_equal(r, d) -@dec.slow -@dec.skipif(np.dtype(np.intp).itemsize < 8, "test requires 64-bit system") +@pytest.mark.skipif(np.dtype(np.intp).itemsize < 8, + reason="test requires 64-bit system") +@pytest.mark.slow def test_large_archive(): # Regression test for product of saving arrays with dimensions of array # having a product that doesn't fit in int32. See gh-7598 for details. diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index c28257c6d..2ea2dbc56 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -4,6 +4,7 @@ import operator import warnings import sys import decimal +import pytest import numpy as np from numpy import ma @@ -11,7 +12,7 @@ from numpy.testing import ( run_module_suite, assert_, assert_equal, assert_array_equal, assert_almost_equal, assert_array_almost_equal, assert_raises, assert_allclose, assert_array_max_ulp, assert_warns, assert_raises_regex, - dec, suppress_warnings, + suppress_warnings, HAS_REFCOUNT, ) import numpy.lib.function_base as nfb from numpy.random import rand @@ -2143,7 +2144,7 @@ class TestBincount(object): "must not be negative", lambda: np.bincount(x, minlength=-1)) - @dec._needs_refcount + @pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts") def test_dtype_reference_leaks(self): # gh-6805 intp_refcount = sys.getrefcount(np.dtype(np.intp)) @@ -2987,7 +2988,7 @@ class TestAdd_newdoc_ufunc(object): class TestAdd_newdoc(object): - @dec.skipif(sys.flags.optimize == 2) + @pytest.mark.skipif(sys.flags.optimize == 2, reason="Python running -OO") def test_add_doc(self): # test np.add_newdoc tgt = "Current flat index into the array." diff --git a/numpy/lib/tests/test_histograms.py b/numpy/lib/tests/test_histograms.py index 4f7af214c..6f73a8d60 100644 --- a/numpy/lib/tests/test_histograms.py +++ b/numpy/lib/tests/test_histograms.py @@ -7,7 +7,7 @@ from numpy.testing import ( run_module_suite, assert_, assert_equal, assert_array_equal, assert_almost_equal, assert_array_almost_equal, assert_raises, assert_allclose, assert_array_max_ulp, assert_warns, assert_raises_regex, - dec, suppress_warnings, HAS_REFCOUNT, + suppress_warnings, ) diff --git a/numpy/lib/tests/test_io.py b/numpy/lib/tests/test_io.py index 5d7dc32dd..0a032ce12 100644 --- a/numpy/lib/tests/test_io.py +++ b/numpy/lib/tests/test_io.py @@ -4,15 +4,16 @@ import sys import gzip import os import threading -from tempfile import NamedTemporaryFile import time import warnings import gc import io +import re +import pytest +from tempfile import NamedTemporaryFile from io import BytesIO, StringIO from datetime import datetime import locale -import re import numpy as np import numpy.ma as ma @@ -20,10 +21,10 @@ from numpy.lib._iotools import ConverterError, ConversionWarning from numpy.compat import asbytes, bytes, unicode, Path from numpy.ma.testutils import assert_equal from numpy.testing import ( - run_module_suite, assert_warns, assert_, SkipTest, - assert_raises_regex, assert_raises, assert_allclose, - assert_array_equal, temppath, tempdir, dec, IS_PYPY, suppress_warnings, -) + run_module_suite, assert_warns, assert_, SkipTest, assert_raises_regex, + assert_raises, assert_allclose, assert_array_equal, temppath, tempdir, + IS_PYPY, HAS_REFCOUNT, suppress_warnings, + ) class TextIO(BytesIO): @@ -156,7 +157,7 @@ class RoundtripTest(object): a = np.array([1, 2, 3, 4], int) self.roundtrip(a) - @dec.knownfailureif(sys.platform == 'win32', "Fail on Win32") + @pytest.mark.skipif(sys.platform == 'win32', reason="Fails on Win32") def test_mmap(self): a = np.array([[1, 2.5], [4, 7.3]]) self.roundtrip(a, file_on_disk=True, load_kwds={'mmap_mode': 'r'}) @@ -168,7 +169,7 @@ class RoundtripTest(object): a = np.array([(1, 2), (3, 4)], dtype=[('x', 'i4'), ('y', 'i4')]) self.check_roundtrips(a) - @dec.slow + @pytest.mark.slow def test_format_2_0(self): dt = [(("%d" % i) * 100, float) for i in range(500)] a = np.ones(1000, dtype=dt) @@ -200,8 +201,8 @@ class TestSavezLoad(RoundtripTest): self.arr_reloaded.fid.close() os.remove(self.arr_reloaded.fid.name) - @dec.skipif(not IS_64BIT, "Works only with 64bit systems") - @dec.slow + @pytest.mark.skipif(not IS_64BIT, reason="Needs 64bit platform") + @pytest.mark.slow def test_big_arrays(self): L = (1 << 31) + 100000 a = np.empty(L, dtype=np.uint8) @@ -277,7 +278,8 @@ class TestSavezLoad(RoundtripTest): fp.seek(0) assert_(not fp.closed) - @dec.skipif(IS_PYPY, "context manager required on PyPy") + #FIXME: Is this still true? + @pytest.mark.skipif(IS_PYPY, reason="Missing context manager on PyPy") def test_closing_fid(self): # Test that issue #1517 (too many opened files) remains closed # It might be a "weak" test since failed to get triggered on @@ -540,15 +542,17 @@ class LoadTxtBase(object): assert_array_equal(res, wanted) # Python2 .open does not support encoding - @dec.skipif(MAJVER == 2) + @pytest.mark.skipif(MAJVER == 2, reason="Needs Python version >= 3") def test_compressed_gzip(self): self.check_compressed(gzip.open, ('.gz',)) - @dec.skipif(MAJVER == 2 or not HAS_BZ2) + @pytest.mark.skipif(not HAS_BZ2, reason="Needs bz2") + @pytest.mark.skipif(MAJVER == 2, reason="Needs Python version >= 3") def test_compressed_gzip(self): self.check_compressed(bz2.open, ('.bz2',)) - @dec.skipif(MAJVER == 2 or not HAS_LZMA) + @pytest.mark.skipif(not HAS_LZMA, reason="Needs lzma") + @pytest.mark.skipif(MAJVER == 2, reason="Needs Python version >= 3") def test_compressed_gzip(self): self.check_compressed(lzma.open, ('.xz', '.lzma')) @@ -1007,7 +1011,8 @@ class TestLoadTxt(LoadTxtBase): dt = np.dtype([('x', int), ('a', 'S10'), ('y', int)]) np.loadtxt(c, delimiter=',', dtype=dt, comments=None) # Should succeed - @dec.skipif(locale.getpreferredencoding() == 'ANSI_X3.4-1968') + @pytest.mark.skipif(locale.getpreferredencoding() == 'ANSI_X3.4-1968', + reason="Wrong preferred encoding") def test_binary_load(self): butf8 = b"5,6,7,\xc3\x95scarscar\n\r15,2,3,hello\n\r"\ b"20,2,3,\xc3\x95scar\n\r" @@ -1984,7 +1989,6 @@ M 33 21.99 # encoding of io.open. Will need to change this for PyTest, maybe # using pytest.mark.xfail(raises=***). try: - import locale encoding = locale.getpreferredencoding() utf8.encode(encoding) except (UnicodeError, ImportError): @@ -2189,9 +2193,9 @@ M 33 21.99 assert_equal(test['f2'], 1024) +@pytest.mark.skipif(Path is None, reason="No pathlib.Path") class TestPathUsage(object): # Test that pathlib.Path can be used - @dec.skipif(Path is None, "No pathlib.Path") def test_loadtxt(self): with temppath(suffix='.txt') as path: path = Path(path) @@ -2200,7 +2204,6 @@ class TestPathUsage(object): x = np.loadtxt(path) assert_array_equal(x, a) - @dec.skipif(Path is None, "No pathlib.Path") def test_save_load(self): # Test that pathlib.Path instances can be used with savez. with temppath(suffix='.npy') as path: @@ -2210,7 +2213,6 @@ class TestPathUsage(object): data = np.load(path) assert_array_equal(data, a) - @dec.skipif(Path is None, "No pathlib.Path") def test_savez_load(self): # Test that pathlib.Path instances can be used with savez. with temppath(suffix='.npz') as path: @@ -2218,8 +2220,7 @@ class TestPathUsage(object): np.savez(path, lab='place holder') with np.load(path) as data: assert_array_equal(data['lab'], 'place holder') - - @dec.skipif(Path is None, "No pathlib.Path") + def test_savez_compressed_load(self): # Test that pathlib.Path instances can be used with savez. with temppath(suffix='.npz') as path: @@ -2229,7 +2230,6 @@ class TestPathUsage(object): assert_array_equal(data['lab'], 'place holder') data.close() - @dec.skipif(Path is None, "No pathlib.Path") def test_genfromtxt(self): with temppath(suffix='.txt') as path: path = Path(path) @@ -2238,7 +2238,6 @@ class TestPathUsage(object): data = np.genfromtxt(path) assert_array_equal(a, data) - @dec.skipif(Path is None, "No pathlib.Path") def test_ndfromtxt(self): # Test outputting a standard ndarray with temppath(suffix='.txt') as path: @@ -2250,7 +2249,6 @@ class TestPathUsage(object): test = np.ndfromtxt(path, dtype=int) assert_array_equal(test, control) - @dec.skipif(Path is None, "No pathlib.Path") def test_mafromtxt(self): # From `test_fancy_dtype_alt` above with temppath(suffix='.txt') as path: @@ -2262,7 +2260,6 @@ class TestPathUsage(object): control = ma.array([(1.0, 2.0, 3.0), (4.0, 5.0, 6.0)]) assert_equal(test, control) - @dec.skipif(Path is None, "No pathlib.Path") def test_recfromtxt(self): with temppath(suffix='.txt') as path: path = Path(path) @@ -2276,7 +2273,6 @@ class TestPathUsage(object): assert_(isinstance(test, np.recarray)) assert_equal(test, control) - @dec.skipif(Path is None, "No pathlib.Path") def test_recfromcsv(self): with temppath(suffix='.txt') as path: path = Path(path) @@ -2364,7 +2360,7 @@ def test_npzfile_dict(): assert_('x' in z.keys()) -@dec._needs_refcount +@pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts") def test_load_refcount(): # Check that objects returned by np.load are directly freed based on # their refcount, rather than needing the gc to collect them. diff --git a/numpy/lib/tests/test_recfunctions.py b/numpy/lib/tests/test_recfunctions.py index bc9f8d7b6..e1b62d46a 100644 --- a/numpy/lib/tests/test_recfunctions.py +++ b/numpy/lib/tests/test_recfunctions.py @@ -1,11 +1,13 @@ from __future__ import division, absolute_import, print_function +import pytest + import numpy as np import numpy.ma as ma from numpy.ma.mrecords import MaskedRecords from numpy.ma.testutils import assert_equal from numpy.testing import ( - run_module_suite, assert_, assert_raises, dec + run_module_suite, assert_, assert_raises, ) from numpy.lib.recfunctions import ( drop_fields, rename_fields, get_fieldstructure, recursive_fill_fields, @@ -687,7 +689,7 @@ class TestJoinBy(object): b = np.ones(3, dtype=[('c', 'u1'), ('b', 'f4'), ('a', 'i4')]) assert_raises(ValueError, join_by, ['a', 'b', 'b'], a, b) - @dec.knownfailureif(True) + @pytest.mark.xfail(reason="See comment at gh-9343") def test_same_name_different_dtypes_key(self): a_dtype = np.dtype([('key', 'S5'), ('value', '<f4')]) b_dtype = np.dtype([('key', 'S10'), ('value', '<f4')]) diff --git a/numpy/lib/tests/test_utils.py b/numpy/lib/tests/test_utils.py index 92bcdc238..7d8e7e68e 100644 --- a/numpy/lib/tests/test_utils.py +++ b/numpy/lib/tests/test_utils.py @@ -1,9 +1,11 @@ from __future__ import division, absolute_import, print_function import sys +import pytest + from numpy.core import arange from numpy.testing import ( - run_module_suite, assert_, assert_equal, assert_raises_regex, dec + run_module_suite, assert_, assert_equal, assert_raises_regex ) from numpy.lib import deprecate import numpy.lib.utils as utils @@ -14,7 +16,7 @@ else: from StringIO import StringIO -@dec.skipif(sys.flags.optimize == 2) +@pytest.mark.skipif(sys.flags.optimize == 2, reason="Python running -OO") def test_lookfor(): out = StringIO() utils.lookfor('eigenvalue', module='numpy', output=out, diff --git a/numpy/linalg/__init__.py b/numpy/linalg/__init__.py index 1510a8448..37bd27574 100644 --- a/numpy/linalg/__init__.py +++ b/numpy/linalg/__init__.py @@ -50,5 +50,6 @@ from .info import __doc__ from .linalg import * -from numpy.testing import _numpy_tester -test = _numpy_tester().test +from numpy.testing._private.pytesttester import PytestTester +test = PytestTester(__name__) +del PytestTester diff --git a/numpy/linalg/tests/test_build.py b/numpy/linalg/tests/test_build.py index b46a72c02..2e9eb7389 100644 --- a/numpy/linalg/tests/test_build.py +++ b/numpy/linalg/tests/test_build.py @@ -3,9 +3,10 @@ from __future__ import division, absolute_import, print_function from subprocess import PIPE, Popen import sys import re +import pytest from numpy.linalg import lapack_lite -from numpy.testing import run_module_suite, assert_, dec +from numpy.testing import run_module_suite, assert_ class FindDependenciesLdd(object): @@ -42,8 +43,8 @@ class FindDependenciesLdd(object): class TestF77Mismatch(object): - @dec.skipif(not(sys.platform[:5] == 'linux'), - "Skipping fortran compiler mismatch on non Linux platform") + @pytest.mark.skipif(not(sys.platform[:5] == 'linux'), + reason="no fortran compiler on non-Linux platform") def test_lapack(self): f = FindDependenciesLdd() deps = f.grep_dependencies(lapack_lite.__file__, @@ -53,5 +54,6 @@ class TestF77Mismatch(object): cause random crashes and wrong results. See numpy INSTALL.txt for more information.""") -if __name__ == "__main__": + +if __name__ == '__main__': run_module_suite() diff --git a/numpy/linalg/tests/test_linalg.py b/numpy/linalg/tests/test_linalg.py index 8372679be..c0147ab64 100644 --- a/numpy/linalg/tests/test_linalg.py +++ b/numpy/linalg/tests/test_linalg.py @@ -8,6 +8,7 @@ import sys import itertools import traceback import warnings +import pytest import numpy as np from numpy import array, single, double, csingle, cdouble, dot, identity @@ -18,8 +19,8 @@ from numpy.linalg.linalg import _multi_dot_matrix_chain_order from numpy.testing import ( assert_, assert_equal, assert_raises, assert_array_equal, assert_almost_equal, assert_allclose, run_module_suite, - dec, SkipTest, suppress_warnings -) + SkipTest, suppress_warnings + ) def ifthen(a, b): @@ -388,35 +389,35 @@ class HermitianTestCase(object): class LinalgGeneralizedSquareTestCase(object): - @dec.slow + @pytest.mark.slow def test_generalized_sq_cases(self): _check_cases(self.do, require={'generalized', 'square'}, exclude={'size-0'}) - @dec.slow + @pytest.mark.slow def test_generalized_empty_sq_cases(self): _check_cases(self.do, require={'generalized', 'square', 'size-0'}) class LinalgGeneralizedNonsquareTestCase(object): - @dec.slow + @pytest.mark.slow def test_generalized_nonsq_cases(self): _check_cases(self.do, require={'generalized', 'nonsquare'}, exclude={'size-0'}) - @dec.slow + @pytest.mark.slow def test_generalized_empty_nonsq_cases(self): _check_cases(self.do, require={'generalized', 'nonsquare', 'size-0'}) class HermitianGeneralizedTestCase(object): - @dec.slow + @pytest.mark.slow def test_generalized_herm_cases(self): _check_cases(self.do, require={'generalized', 'hermitian'}, exclude={'size-0'}) - @dec.slow + @pytest.mark.slow def test_generalized_empty_herm_cases(self): _check_cases(self.do, require={'generalized', 'hermitian', 'size-0'}, diff --git a/numpy/ma/__init__.py b/numpy/ma/__init__.py index 0689f2932..34f21b8b1 100644 --- a/numpy/ma/__init__.py +++ b/numpy/ma/__init__.py @@ -51,5 +51,6 @@ __all__ = ['core', 'extras'] __all__ += core.__all__ __all__ += extras.__all__ -from numpy.testing import _numpy_tester -test = _numpy_tester().test +from numpy.testing._private.pytesttester import PytestTester +test = PytestTester(__name__) +del PytestTester diff --git a/numpy/ma/tests/test_core.py b/numpy/ma/tests/test_core.py index ff1e087b5..69be64986 100644 --- a/numpy/ma/tests/test_core.py +++ b/numpy/ma/tests/test_core.py @@ -13,8 +13,9 @@ import warnings import pickle import operator import itertools -import sys import textwrap +import pytest + from functools import reduce @@ -23,7 +24,7 @@ import numpy.ma.core import numpy.core.fromnumeric as fromnumeric import numpy.core.umath as umath from numpy.testing import ( - run_module_suite, assert_raises, assert_warns, suppress_warnings, dec + run_module_suite, assert_raises, assert_warns, suppress_warnings ) from numpy import ndarray from numpy.compat import asbytes, asbytes_nested @@ -49,7 +50,6 @@ from numpy.ma.core import ( ravel, repeat, reshape, resize, shape, sin, sinh, sometrue, sort, sqrt, subtract, sum, take, tan, tanh, transpose, where, zeros, ) -from numpy.testing import dec pi = np.pi @@ -3728,8 +3728,8 @@ class TestMaskedArrayMathMethods(object): assert_almost_equal(np.sqrt(mXvar0[k]), mX[:, k].compressed().std()) - @dec.knownfailureif(sys.platform=='win32' and sys.version_info < (3, 6), - msg='Fails on Python < 3.6 (Issue #9671)') + @pytest.mark.skipif(sys.platform=='win32' and sys.version_info < (3, 6), + reason='Fails on Python < 3.6 on Windows, gh-9671') @suppress_copy_mask_on_assignment def test_varstd_specialcases(self): # Test a special case for var @@ -4957,7 +4957,8 @@ class TestMaskedConstant(object): assert_raises(MaskError, operator.setitem, a_i, (), np.ma.masked) assert_raises(MaskError, int, np.ma.masked) - @dec.skipif(sys.version_info.major == 3, "long doesn't exist in Python 3") + @pytest.mark.skipif(sys.version_info.major == 3, + reason="long doesn't exist in Python 3") def test_coercion_long(self): assert_raises(MaskError, long, np.ma.masked) @@ -4966,13 +4967,13 @@ class TestMaskedConstant(object): assert_warns(UserWarning, operator.setitem, a_f, (), np.ma.masked) assert_(np.isnan(a_f[()])) - @dec.knownfailureif(True, "See gh-9750") + @pytest.mark.xfail(reason="See gh-9750") def test_coercion_unicode(self): a_u = np.zeros((), 'U10') a_u[()] = np.ma.masked assert_equal(a_u[()], u'--') - @dec.knownfailureif(True, "See gh-9750") + @pytest.mark.xfail(reason="See gh-9750") def test_coercion_bytes(self): a_b = np.zeros((), 'S10') a_b[()] = np.ma.masked diff --git a/numpy/ma/tests/test_subclassing.py b/numpy/ma/tests/test_subclassing.py index a54574690..dec8a9cef 100644 --- a/numpy/ma/tests/test_subclassing.py +++ b/numpy/ma/tests/test_subclassing.py @@ -9,7 +9,7 @@ from __future__ import division, absolute_import, print_function import numpy as np -from numpy.testing import run_module_suite, assert_, assert_raises, dec +from numpy.testing import run_module_suite, assert_, assert_raises from numpy.ma.testutils import assert_equal from numpy.ma.core import ( array, arange, masked, MaskedArray, masked_array, log, add, hypot, diff --git a/numpy/matrixlib/__init__.py b/numpy/matrixlib/__init__.py index 95713580d..3ad3a9549 100644 --- a/numpy/matrixlib/__init__.py +++ b/numpy/matrixlib/__init__.py @@ -7,5 +7,6 @@ from .defmatrix import * __all__ = defmatrix.__all__ -from numpy.testing import _numpy_tester -test = _numpy_tester().test +from numpy.testing._private.pytesttester import PytestTester +test = PytestTester(__name__) +del PytestTester diff --git a/numpy/polynomial/__init__.py b/numpy/polynomial/__init__.py index f7cbc19b0..c18bebedb 100644 --- a/numpy/polynomial/__init__.py +++ b/numpy/polynomial/__init__.py @@ -22,5 +22,6 @@ from .hermite import Hermite from .hermite_e import HermiteE from .laguerre import Laguerre -from numpy.testing import _numpy_tester -test = _numpy_tester().test +from numpy.testing._private.pytesttester import PytestTester +test = PytestTester(__name__) +del PytestTester diff --git a/numpy/random/__init__.py b/numpy/random/__init__.py index 409f50ec0..81cb94cc1 100644 --- a/numpy/random/__init__.py +++ b/numpy/random/__init__.py @@ -117,5 +117,6 @@ def __RandomState_ctor(): """ return RandomState(seed=0) -from numpy.testing import _numpy_tester -test = _numpy_tester().test +from numpy.testing._private.pytesttester import PytestTester +test = PytestTester(__name__) +del PytestTester diff --git a/numpy/testing/__init__.py b/numpy/testing/__init__.py index f4970b06b..a7c85931c 100644 --- a/numpy/testing/__init__.py +++ b/numpy/testing/__init__.py @@ -12,9 +12,11 @@ from unittest import TestCase from ._private.utils import * from ._private import decorators as dec from ._private.nosetester import ( - run_module_suite, NoseTester as Tester, _numpy_tester, + run_module_suite, NoseTester as Tester ) __all__ = _private.utils.__all__ + ['TestCase', 'run_module_suite'] -test = _numpy_tester().test +from ._private.pytesttester import PytestTester +test = PytestTester(__name__) +del PytestTester diff --git a/numpy/testing/_private/pytesttester.py b/numpy/testing/_private/pytesttester.py index 6a92a52fd..8c73fafa4 100644 --- a/numpy/testing/_private/pytesttester.py +++ b/numpy/testing/_private/pytesttester.py @@ -32,6 +32,7 @@ import os __all__ = ['PytestTester'] + def _show_numpy_info(): import numpy as np @@ -68,8 +69,8 @@ class PytestTester(object): def __init__(self, module_name): self.module_name = module_name - def test(self, label='fast', verbose=1, extra_argv=None, - doctests=False, coverage=False, timer=0, tests=None): + def __call__(self, label='fast', verbose=1, extra_argv=None, + doctests=False, coverage=False, durations=-1, tests=None): """ Run tests for module using pytest. @@ -88,9 +89,9 @@ class PytestTester(object): coverage : bool, optional If True, report coverage of NumPy code. Default is False. Requires installation of (pip) pytest-cov. - timer : int, optional - If > 0, report the time of the slowest `timer` tests. Default is 0. - + durations : int, optional + If < 0, do nothing, If 0, report time of all tests, if > 0, + report the time of the slowest `timer` tests. Default is -1. tests : test or list of tests Tests to be executed with pytest '--pyargs' @@ -122,6 +123,7 @@ class PytestTester(object): """ import pytest + import warnings #FIXME This is no longer needed? Assume it was for use in tests. # cap verbosity at 3, which is equivalent to the pytest '-vv' option @@ -134,7 +136,26 @@ class PytestTester(object): module_path = os.path.abspath(module.__path__[0]) # setup the pytest arguments - pytest_args = ['-l'] + pytest_args = ["-l"] + + # offset verbosity. The "-q" cancels a "-v". + pytest_args += ["-q"] + + # Filter out distutils cpu warnings (could be localized to + # distutils tests). ASV has problems with top level import, + # so fetch module for suppression here. + with warnings.catch_warnings(): + warnings.simplefilter("always") + from numpy.distutils import cpuinfo + + # Filter out annoying import messages. Want these in both develop and + # release mode. + pytest_args += [ + "-W ignore:Not importing directory", + "-W ignore:numpy.dtype size changed", + "-W ignore:numpy.ufunc size changed", + "-W ignore::UserWarning:cpuinfo", + ] if doctests: raise ValueError("Doctests not supported") @@ -144,8 +165,6 @@ class PytestTester(object): if verbose > 1: pytest_args += ["-" + "v"*(verbose - 1)] - else: - pytest_args += ["-q"] if coverage: pytest_args += ["--cov=" + module_path] @@ -155,13 +174,13 @@ class PytestTester(object): elif label != "full": pytest_args += ["-m", label] - if timer > 0: - pytest_args += ["--durations=%s" % timer] + if durations >= 0: + pytest_args += ["--durations=%s" % durations] if tests is None: tests = [self.module_name] - pytest_args += ['--pyargs'] + list(tests) + pytest_args += ["--pyargs"] + list(tests) # run tests. diff --git a/numpy/testing/tests/test_decorators.py b/numpy/testing/tests/test_decorators.py index 62329ab7d..26be1e359 100644 --- a/numpy/testing/tests/test_decorators.py +++ b/numpy/testing/tests/test_decorators.py @@ -5,195 +5,216 @@ Test the decorators from ``testing.decorators``. from __future__ import division, absolute_import, print_function import warnings +import pytest -from numpy.testing import (dec, assert_, assert_raises, run_module_suite, - SkipTest, KnownFailureException) +from numpy.testing import ( + assert_, assert_raises, run_module_suite, dec, SkipTest, + KnownFailureException, + ) -def test_slow(): - @dec.slow - def slow_func(x, y, z): - pass - - assert_(slow_func.slow) +try: + import nose +except ImportError: + HAVE_NOSE = False +else: + HAVE_NOSE = True -def test_setastest(): - @dec.setastest() - def f_default(a): - pass - - @dec.setastest(True) - def f_istest(a): - pass +@pytest.mark.skipif(not HAVE_NOSE, reason="Needs nose") +class TestNoseDecorators(object): + # These tests are run in a class for simplicity while still + # getting a report on each, skipped or success. - @dec.setastest(False) - def f_isnottest(a): + class DidntSkipException(Exception): pass - assert_(f_default.__test__) - assert_(f_istest.__test__) - assert_(not f_isnottest.__test__) - - -class DidntSkipException(Exception): - pass - -def test_skip_functions_hardcoded(): - @dec.skipif(True) - def f1(x): - raise DidntSkipException - - try: - f1('a') - except DidntSkipException: - raise Exception('Failed to skip') - except SkipTest().__class__: - pass + def test_slow(self): + import nose + @dec.slow + def slow_func(x, y, z): + pass - @dec.skipif(False) - def f2(x): - raise DidntSkipException - - try: - f2('a') - except DidntSkipException: - pass - except SkipTest().__class__: - raise Exception('Skipped when not expected to') + assert_(slow_func.slow) + def test_setastest(self): + @dec.setastest() + def f_default(a): + pass -def test_skip_functions_callable(): - def skip_tester(): - return skip_flag == 'skip me!' + @dec.setastest(True) + def f_istest(a): + pass - @dec.skipif(skip_tester) - def f1(x): - raise DidntSkipException + @dec.setastest(False) + def f_isnottest(a): + pass - try: - skip_flag = 'skip me!' - f1('a') - except DidntSkipException: - raise Exception('Failed to skip') - except SkipTest().__class__: - pass + assert_(f_default.__test__) + assert_(f_istest.__test__) + assert_(not f_isnottest.__test__) - @dec.skipif(skip_tester) - def f2(x): - raise DidntSkipException - try: - skip_flag = 'five is right out!' - f2('a') - except DidntSkipException: - pass - except SkipTest().__class__: - raise Exception('Skipped when not expected to') + def test_skip_functions_hardcoded(self): + @dec.skipif(True) + def f1(x): + raise self.DidntSkipException + try: + f1('a') + except self.DidntSkipException: + raise Exception('Failed to skip') + except SkipTest().__class__: + pass -def test_skip_generators_hardcoded(): - @dec.knownfailureif(True, "This test is known to fail") - def g1(x): - for i in range(x): - yield i + @dec.skipif(False) + def f2(x): + raise self.DidntSkipException - try: - for j in g1(10): + try: + f2('a') + except self.DidntSkipException: + pass + except SkipTest().__class__: + raise Exception('Skipped when not expected to') + + def test_skip_functions_callable(self): + def skip_tester(): + return skip_flag == 'skip me!' + + @dec.skipif(skip_tester) + def f1(x): + raise self.DidntSkipException + + try: + skip_flag = 'skip me!' + f1('a') + except self.DidntSkipException: + raise Exception('Failed to skip') + except SkipTest().__class__: pass - except KnownFailureException().__class__: - pass - else: - raise Exception('Failed to mark as known failure') - @dec.knownfailureif(False, "This test is NOT known to fail") - def g2(x): - for i in range(x): - yield i - raise DidntSkipException('FAIL') + @dec.skipif(skip_tester) + def f2(x): + raise self.DidntSkipException - try: - for j in g2(10): + try: + skip_flag = 'five is right out!' + f2('a') + except self.DidntSkipException: + pass + except SkipTest().__class__: + raise Exception('Skipped when not expected to') + + def test_skip_generators_hardcoded(self): + @dec.knownfailureif(True, "This test is known to fail") + def g1(x): + for i in range(x): + yield i + + try: + for j in g1(10): + pass + except KnownFailureException().__class__: + pass + else: + raise Exception('Failed to mark as known failure') + + @dec.knownfailureif(False, "This test is NOT known to fail") + def g2(x): + for i in range(x): + yield i + raise self.DidntSkipException('FAIL') + + try: + for j in g2(10): + pass + except KnownFailureException().__class__: + raise Exception('Marked incorrectly as known failure') + except self.DidntSkipException: pass - except KnownFailureException().__class__: - raise Exception('Marked incorrectly as known failure') - except DidntSkipException: - pass - -def test_skip_generators_callable(): - def skip_tester(): - return skip_flag == 'skip me!' + def test_skip_generators_callable(self): + def skip_tester(): + return skip_flag == 'skip me!' - @dec.knownfailureif(skip_tester, "This test is known to fail") - def g1(x): - for i in range(x): - yield i + @dec.knownfailureif(skip_tester, "This test is known to fail") + def g1(x): + for i in range(x): + yield i - try: - skip_flag = 'skip me!' - for j in g1(10): + try: + skip_flag = 'skip me!' + for j in g1(10): + pass + except KnownFailureException().__class__: pass - except KnownFailureException().__class__: - pass - else: - raise Exception('Failed to mark as known failure') - - @dec.knownfailureif(skip_tester, "This test is NOT known to fail") - def g2(x): - for i in range(x): - yield i - raise DidntSkipException('FAIL') - - try: - skip_flag = 'do not skip' - for j in g2(10): + else: + raise Exception('Failed to mark as known failure') + + @dec.knownfailureif(skip_tester, "This test is NOT known to fail") + def g2(x): + for i in range(x): + yield i + raise self.DidntSkipException('FAIL') + + try: + skip_flag = 'do not skip' + for j in g2(10): + pass + except KnownFailureException().__class__: + raise Exception('Marked incorrectly as known failure') + except self.DidntSkipException: pass - except KnownFailureException().__class__: - raise Exception('Marked incorrectly as known failure') - except DidntSkipException: - pass + def test_deprecated(self): + @dec.deprecated(True) + def non_deprecated_func(): + pass -def test_deprecated(): - @dec.deprecated(True) - def non_deprecated_func(): - pass - - @dec.deprecated() - def deprecated_func(): - import warnings - warnings.warn("TEST: deprecated func", DeprecationWarning) - - @dec.deprecated() - def deprecated_func2(): - import warnings - warnings.warn("AHHHH") - raise ValueError - - @dec.deprecated() - def deprecated_func3(): - import warnings - warnings.warn("AHHHH") - - # marked as deprecated, but does not raise DeprecationWarning - assert_raises(AssertionError, non_deprecated_func) - # should be silent - deprecated_func() - with warnings.catch_warnings(record=True): - warnings.simplefilter("always") # do not propagate unrelated warnings - # fails if deprecated decorator just disables test. See #1453. - assert_raises(ValueError, deprecated_func2) - # warning is not a DeprecationWarning - assert_raises(AssertionError, deprecated_func3) - - -@dec.parametrize('base, power, expected', - [(1, 1, 1), - (2, 1, 2), - (2, 2, 4)]) -def test_parametrize(base, power, expected): - assert_(base**power == expected) + @dec.deprecated() + def deprecated_func(): + import warnings + warnings.warn("TEST: deprecated func", DeprecationWarning) + + @dec.deprecated() + def deprecated_func2(): + import warnings + warnings.warn("AHHHH") + raise ValueError + + @dec.deprecated() + def deprecated_func3(): + import warnings + warnings.warn("AHHHH") + + # marked as deprecated, but does not raise DeprecationWarning + assert_raises(AssertionError, non_deprecated_func) + # should be silent + deprecated_func() + with warnings.catch_warnings(record=True): + warnings.simplefilter("always") # do not propagate unrelated warnings + # fails if deprecated decorator just disables test. See #1453. + assert_raises(ValueError, deprecated_func2) + # warning is not a DeprecationWarning + assert_raises(AssertionError, deprecated_func3) + + def test_parametrize(self): + # dec.parametrize assumes that it is being run by nose. Because + # we are running under pytest, we need to explicitly check the + # results. + @dec.parametrize('base, power, expected', + [(1, 1, 1), + (2, 1, 2), + (2, 2, 4)]) + def check_parametrize(base, power, expected): + assert_(base**power == expected) + + count = 0 + for test in check_parametrize(): + test[0](*test[1:]) + count += 1 + assert_(count == 3) if __name__ == '__main__': diff --git a/numpy/testing/tests/test_doctesting.py b/numpy/testing/tests/test_doctesting.py index 43f9fb6ce..b77cd93e0 100644 --- a/numpy/testing/tests/test_doctesting.py +++ b/numpy/testing/tests/test_doctesting.py @@ -3,6 +3,9 @@ """ from __future__ import division, absolute_import, print_function +#FIXME: None of these tests is run, because 'check' is not a recognized +# testing prefix. + # try the #random directive on the output line def check_random_directive(): ''' diff --git a/numpy/testing/tests/test_utils.py b/numpy/testing/tests/test_utils.py index d5c582ad3..4ba484ba0 100644 --- a/numpy/testing/tests/test_utils.py +++ b/numpy/testing/tests/test_utils.py @@ -5,6 +5,7 @@ import sys import os import itertools import textwrap +import pytest import numpy as np from numpy.testing import ( @@ -659,7 +660,7 @@ class TestArrayAssertLess(object): assert_raises(AssertionError, lambda: self._assert_func(-ainf, -x)) self._assert_func(-ainf, x) - +@pytest.mark.skip(reason="The raises decorator depends on Nose") class TestRaises(object): def setup(self): diff --git a/numpy/tests/test_ctypeslib.py b/numpy/tests/test_ctypeslib.py index e8043d057..a208c9073 100644 --- a/numpy/tests/test_ctypeslib.py +++ b/numpy/tests/test_ctypeslib.py @@ -1,11 +1,12 @@ from __future__ import division, absolute_import, print_function import sys +import pytest import numpy as np from numpy.ctypeslib import ndpointer, load_library from numpy.distutils.misc_util import get_shared_lib_extension -from numpy.testing import run_module_suite, assert_, assert_raises, dec +from numpy.testing import run_module_suite, assert_, assert_raises try: cdll = None @@ -21,10 +22,10 @@ except ImportError: _HAS_CTYPE = False class TestLoadLibrary(object): - @dec.skipif(not _HAS_CTYPE, - "ctypes not available on this python installation") - @dec.knownfailureif(sys.platform == - 'cygwin', "This test is known to fail on cygwin") + @pytest.mark.skipif(not _HAS_CTYPE, + reason="ctypes not available in this python") + @pytest.mark.skipif(sys.platform == 'cygwin', + reason="Known to fail on cygwin") def test_basic(self): try: # Should succeed @@ -34,10 +35,10 @@ class TestLoadLibrary(object): " (import error was: %s)" % str(e)) print(msg) - @dec.skipif(not _HAS_CTYPE, - "ctypes not available on this python installation") - @dec.knownfailureif(sys.platform == - 'cygwin', "This test is known to fail on cygwin") + @pytest.mark.skipif(not _HAS_CTYPE, + reason="ctypes not available in this python") + @pytest.mark.skipif(sys.platform == 'cygwin', + reason="Known to fail on cygwin") def test_basic2(self): # Regression for #801: load_library with a full library name # (including extension) does not work. diff --git a/numpy/tests/test_scripts.py b/numpy/tests/test_scripts.py index 675fe6575..ee09390c7 100644 --- a/numpy/tests/test_scripts.py +++ b/numpy/tests/test_scripts.py @@ -4,14 +4,15 @@ Test that we can run executable scripts that have been installed with numpy. """ from __future__ import division, print_function, absolute_import +import sys import os +import pytest from os.path import join as pathjoin, isfile, dirname, basename -import sys from subprocess import Popen, PIPE + import numpy as np from numpy.compat.py3k import basestring -from nose.tools import assert_equal -from numpy.testing import assert_, dec +from numpy.testing import assert_, assert_equal is_inplace = isfile(pathjoin(dirname(np.__file__), '..', 'setup.py')) @@ -58,7 +59,7 @@ def run_command(cmd, check_code=True): return proc.returncode, stdout, stderr -@dec.skipif(is_inplace) +@pytest.mark.skipif(is_inplace, reason="Cannot test f2py command inplace") def test_f2py(): # test that we can run f2py script if sys.platform == 'win32': diff --git a/numpy/tests/test_warnings.py b/numpy/tests/test_warnings.py index 7f22794ec..abebdafc8 100644 --- a/numpy/tests/test_warnings.py +++ b/numpy/tests/test_warnings.py @@ -2,18 +2,17 @@ Tests which scan for certain occurrences in the code, they may not find all of these occurrences but should catch almost all. """ - - from __future__ import division, absolute_import, print_function - import sys +import pytest + if sys.version_info >= (3, 4): from pathlib import Path import ast import tokenize import numpy - from numpy.testing import run_module_suite, dec + from numpy.testing import run_module_suite class ParseCall(ast.NodeVisitor): def __init__(self): @@ -61,7 +60,7 @@ if sys.version_info >= (3, 4): "{} on line {}".format(self.__filename, node.lineno)) - @dec.slow + @pytest.mark.slow def test_warning_calls(): # combined "ignore" and stacklevel error base = Path(numpy.__file__).parent diff --git a/pytest.ini b/pytest.ini index e901beb8c..2423857b0 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,5 +1,5 @@ [pytest] -addopts = -l -q +addopts = -l norecursedirs = doc tools numpy/linalg/lapack_lite numpy/core/code_generators doctest_optionflags = NORMALIZE_WHITESPACE diff --git a/runtests.py b/runtests.py index d06b241f0..12e3f2886 100755 --- a/runtests.py +++ b/runtests.py @@ -9,11 +9,10 @@ Examples:: $ python runtests.py $ python runtests.py -s {SAMPLE_SUBMODULE} $ python runtests.py -t {SAMPLE_TEST} - $ python runtests.py -t {SAMPLE_TEST} -- {SAMPLE_NOSE_ARGUMENTS} $ python runtests.py --ipython $ python runtests.py --python somescript.py $ python runtests.py --bench - $ python runtests.py --timer 20 + $ python runtests.py --durations 20 Run a debugger: @@ -37,7 +36,6 @@ PROJECT_MODULE = "numpy" PROJECT_ROOT_FILES = ['numpy', 'LICENSE.txt', 'setup.py'] SAMPLE_TEST = "numpy/linalg/tests/test_linalg.py:test_byteorder_check" SAMPLE_SUBMODULE = "linalg" -SAMPLE_NOSE_ARGUMENTS = "--pdb" EXTRA_PATH = ['/usr/lib/ccache', '/usr/lib/f90cache', '/usr/local/lib/ccache', '/usr/local/lib/f90cache'] @@ -75,11 +73,13 @@ def main(argv): help="just build, do not run any tests") parser.add_argument("--doctests", action="store_true", default=False, help="Run doctests in module") + #parser.add_argument("--refguide-check", action="store_true", default=False, + #help="Run refguide check (do not run regular tests.)") parser.add_argument("--coverage", action="store_true", default=False, help=("report coverage of project code. HTML output goes " "under build/coverage")) - parser.add_argument("--timer", action="store", default=0, type=int, - help=("Time N slowest test")) + parser.add_argument("--durations", action="store", default=-1, type=int, + help=("Time N slowest tests, time all if 0, time none if < 0")) parser.add_argument("--gcov", action="store_true", default=False, help=("enable C code coverage via gcov (requires GCC). " "gcov output goes to build/**/*.gc*")) @@ -111,25 +111,17 @@ def main(argv): parser.add_argument("--bench", action="store_true", help="Run benchmark suite instead of test suite") parser.add_argument("--bench-compare", action="store", metavar="COMMIT", - help=("Compare benchmark results to COMMIT. " - "Note that you need to commit your changes first!")) - parser.add_argument("--raise-warnings", default=None, type=str, - choices=('develop', 'release'), - help=("if 'develop', warnings are treated as errors; " - "defaults to 'develop' in development versions.")) + help=("Compare benchmark results of current HEAD to " + "BEFORE. Use an additional " + "--bench-compare=COMMIT to override HEAD with " + "COMMIT. Note that you need to commit your " + "changes first!")) parser.add_argument("args", metavar="ARGS", default=[], nargs=REMAINDER, help="Arguments to pass to Nose, Python or shell") args = parser.parse_args(argv) - if args.timer == 0: - timer = False - elif args.timer == -1: - timer = True - elif args.timer > 0: - timer = int(args.timer) - else: - raise ValueError("--timer value should be an integer, -1 or >0") - args.timer = timer + if args.durations < 0: + args.durations = -1 if args.bench_compare: args.bench = True @@ -208,8 +200,7 @@ def main(argv): fn = os.path.join(dst_dir, 'coverage_html.js') if os.path.isdir(dst_dir) and os.path.isfile(fn): shutil.rmtree(dst_dir) - extra_argv += ['--cover-html', - '--cover-html-dir='+dst_dir] + extra_argv += ['--cov-report=html:' + dst_dir] if args.bench: # Run ASV @@ -264,48 +255,29 @@ def main(argv): if args.build_only: sys.exit(0) - elif args.submodule: - modname = PROJECT_MODULE + '.' + args.submodule - try: - __import__(modname) - test = sys.modules[modname].test - except (ImportError, KeyError, AttributeError): - print("Cannot run tests for %s" % modname) - sys.exit(2) - elif args.tests: - def fix_test_path(x): - # fix up test path - p = x.split(':') - p[0] = os.path.join(site_dir, p[0]) - return ':'.join(p) - - tests = [fix_test_path(x) for x in args.tests] - - def test(*a, **kw): - extra_argv = kw.pop('extra_argv', ()) - extra_argv = extra_argv + tests[1:] - kw['extra_argv'] = extra_argv - import numpy as np - from numpy.testing import Tester - if kw["raise_warnings"] is None: - if hasattr(np, "__version__") and ".dev0" in np.__version__: - kw["raise_warnings"] = "develop" - else: - kw["raise_warnings"] = "release" - return Tester(tests[0]).test(*a, **kw) else: __import__(PROJECT_MODULE) test = sys.modules[PROJECT_MODULE].test + if args.submodule: + tests = [PROJECT_MODULE + "." + args.submodule] + elif args.tests: + tests = args.tests + else: + tests = None + + # Run the tests under build/test - try: - shutil.rmtree(test_dir) - except OSError: - pass - try: - os.makedirs(test_dir) - except OSError: - pass + + if not args.no_build: + test_dir = site_dir + else: + test_dir = os.path.join(ROOT_DIR, 'build', 'test') + if not os.path.isdir(test_dir): + os.makedirs(test_dir) + + shutil.copyfile(os.path.join(ROOT_DIR, '.coveragerc'), + os.path.join(test_dir, '.coveragerc')) cwd = os.getcwd() try: @@ -314,13 +286,15 @@ def main(argv): verbose=args.verbose, extra_argv=extra_argv, doctests=args.doctests, - raise_warnings=args.raise_warnings, coverage=args.coverage, - timer=args.timer) + durations=args.durations, + tests=tests) finally: os.chdir(cwd) - if result.wasSuccessful(): + if isinstance(result, bool): + sys.exit(0 if result else 1) + elif result.wasSuccessful(): sys.exit(0) else: sys.exit(1) diff --git a/tools/test-installed-numpy.py b/tools/test-installed-numpy.py index 26a50b2fa..04a2a1da2 100644 --- a/tools/test-installed-numpy.py +++ b/tools/test-installed-numpy.py @@ -27,11 +27,11 @@ parser.add_option("--doctests", help="Run doctests in module") parser.add_option("--coverage", action="store_true", dest="coverage", default=False, - help="report coverage of NumPy code (requires 'coverage' module") + help="report coverage of NumPy code (requires 'pytest-cov' module") parser.add_option("-m", "--mode", action="store", dest="mode", default="fast", help="'fast', 'full', or something that could be " - "passed to nosetests -A [default: %default]") + "passed to pytest [default: %default]") (options, args) = parser.parse_args() import numpy @@ -52,7 +52,7 @@ result = numpy.test(options.mode, doctests=options.doctests, coverage=options.coverage) -if result.wasSuccessful(): +if result: sys.exit(0) else: sys.exit(1) diff --git a/tools/travis-before-install.sh b/tools/travis-before-install.sh index 5e5278ce5..1671d35b4 100755 --- a/tools/travis-before-install.sh +++ b/tools/travis-before-install.sh @@ -26,6 +26,6 @@ fi source venv/bin/activate python -V pip install --upgrade pip setuptools -pip install nose pytz cython +pip install nose pytz cython pytest if [ -n "$USE_ASV" ]; then pip install asv; fi popd diff --git a/tools/travis-test.sh b/tools/travis-test.sh index bd9f79c22..70c512ea1 100755 --- a/tools/travis-test.sh +++ b/tools/travis-test.sh @@ -95,7 +95,8 @@ setup_chroot() # install needed packages sudo chroot $DIR bash -c "apt-get install -qq -y \ - libatlas-base-dev gfortran python-dev python-nose python-pip cython" + libatlas-base-dev gfortran python-dev python-nose python-pip cython \ + python-pytest" } run_test() @@ -112,9 +113,11 @@ run_test() "import os; import numpy; print(os.path.dirname(numpy.__file__))") export PYTHONWARNINGS=default if [ -n "$RUN_FULL_TESTS" ]; then - $PYTHON ../tools/test-installed-numpy.py --mode=full + $PYTHON ../tools/test-installed-numpy.py -v --mode=full -- \ + --disable-pytest-warnings else - $PYTHON ../tools/test-installed-numpy.py + $PYTHON ../tools/test-installed-numpy.py -v -- \ + --disable-pytest-warnings fi if [ -n "$USE_ASV" ]; then pushd ../benchmarks @@ -147,7 +150,7 @@ if [ -n "$USE_WHEEL" ] && [ $# -eq 0 ]; then # Move out of source directory to avoid finding local numpy pushd dist pip install --pre --no-index --upgrade --find-links=. numpy - pip install nose + pip install nose pytest popd run_test elif [ -n "$USE_SDIST" ] && [ $# -eq 0 ]; then @@ -164,7 +167,7 @@ elif [ -n "$USE_SDIST" ] && [ $# -eq 0 ]; then # Move out of source directory to avoid finding local numpy pushd dist pip install numpy* - pip install nose + pip install nose pytest popd run_test elif [ -n "$USE_CHROOT" ] && [ $# -eq 0 ]; then |