You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					207 lines
				
				6.5 KiB
			
		
		
			
		
	
	
					207 lines
				
				6.5 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								"""
							 | 
						||
| 
								 | 
							
								Pytest test running.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This module implements the ``test()`` function for NumPy modules. The usual
							 | 
						||
| 
								 | 
							
								boiler plate for doing that is to put the following in the module
							 | 
						||
| 
								 | 
							
								``__init__.py`` file::
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    from numpy._pytesttester import PytestTester
							 | 
						||
| 
								 | 
							
								    test = PytestTester(__name__)
							 | 
						||
| 
								 | 
							
								    del PytestTester
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Warnings filtering and other runtime settings should be dealt with in the
							 | 
						||
| 
								 | 
							
								``pytest.ini`` file in the numpy repo root. The behavior of the test depends on
							 | 
						||
| 
								 | 
							
								whether or not that file is found as follows:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* ``pytest.ini`` is present (develop mode)
							 | 
						||
| 
								 | 
							
								    All warnings except those explicitly filtered out are raised as error.
							 | 
						||
| 
								 | 
							
								* ``pytest.ini`` is absent (release mode)
							 | 
						||
| 
								 | 
							
								    DeprecationWarnings and PendingDeprecationWarnings are ignored, other
							 | 
						||
| 
								 | 
							
								    warnings are passed through.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								In practice, tests run from the numpy repo are run in develop mode. That
							 | 
						||
| 
								 | 
							
								includes the standard ``python runtests.py`` invocation.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This module is imported by every numpy subpackage, so lies at the top level to
							 | 
						||
| 
								 | 
							
								simplify circular import issues. For the same reason, it contains no numpy
							 | 
						||
| 
								 | 
							
								imports at module scope, instead importing numpy within function calls.
							 | 
						||
| 
								 | 
							
								"""
							 | 
						||
| 
								 | 
							
								import sys
							 | 
						||
| 
								 | 
							
								import os
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								__all__ = ['PytestTester']
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def _show_numpy_info():
							 | 
						||
| 
								 | 
							
								    import numpy as np
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    print("NumPy version %s" % np.__version__)
							 | 
						||
| 
								 | 
							
								    relaxed_strides = np.ones((10, 1), order="C").flags.f_contiguous
							 | 
						||
| 
								 | 
							
								    print("NumPy relaxed strides checking option:", relaxed_strides)
							 | 
						||
| 
								 | 
							
								    info = np.lib.utils._opt_info()
							 | 
						||
| 
								 | 
							
								    print("NumPy CPU features: ", (info if info else 'nothing enabled'))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class PytestTester:
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Pytest test runner.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    A test function is typically added to a package's __init__.py like so::
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      from numpy._pytesttester import PytestTester
							 | 
						||
| 
								 | 
							
								      test = PytestTester(__name__).test
							 | 
						||
| 
								 | 
							
								      del PytestTester
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Calling this test function finds and runs all tests associated with the
							 | 
						||
| 
								 | 
							
								    module and all its sub-modules.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Attributes
							 | 
						||
| 
								 | 
							
								    ----------
							 | 
						||
| 
								 | 
							
								    module_name : str
							 | 
						||
| 
								 | 
							
								        Full path to the package to test.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Parameters
							 | 
						||
| 
								 | 
							
								    ----------
							 | 
						||
| 
								 | 
							
								    module_name : module name
							 | 
						||
| 
								 | 
							
								        The name of the module to test.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Notes
							 | 
						||
| 
								 | 
							
								    -----
							 | 
						||
| 
								 | 
							
								    Unlike the previous ``nose``-based implementation, this class is not
							 | 
						||
| 
								 | 
							
								    publicly exposed as it performs some ``numpy``-specific warning
							 | 
						||
| 
								 | 
							
								    suppression.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    def __init__(self, module_name):
							 | 
						||
| 
								 | 
							
								        self.module_name = module_name
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __call__(self, label='fast', verbose=1, extra_argv=None,
							 | 
						||
| 
								 | 
							
								                 doctests=False, coverage=False, durations=-1, tests=None):
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Run tests for module using pytest.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Parameters
							 | 
						||
| 
								 | 
							
								        ----------
							 | 
						||
| 
								 | 
							
								        label : {'fast', 'full'}, optional
							 | 
						||
| 
								 | 
							
								            Identifies the tests to run. When set to 'fast', tests decorated
							 | 
						||
| 
								 | 
							
								            with `pytest.mark.slow` are skipped, when 'full', the slow marker
							 | 
						||
| 
								 | 
							
								            is ignored.
							 | 
						||
| 
								 | 
							
								        verbose : int, optional
							 | 
						||
| 
								 | 
							
								            Verbosity value for test outputs, in the range 1-3. Default is 1.
							 | 
						||
| 
								 | 
							
								        extra_argv : list, optional
							 | 
						||
| 
								 | 
							
								            List with any extra arguments to pass to pytests.
							 | 
						||
| 
								 | 
							
								        doctests : bool, optional
							 | 
						||
| 
								 | 
							
								            .. note:: Not supported
							 | 
						||
| 
								 | 
							
								        coverage : bool, optional
							 | 
						||
| 
								 | 
							
								            If True, report coverage of NumPy code. Default is False.
							 | 
						||
| 
								 | 
							
								            Requires installation of (pip) pytest-cov.
							 | 
						||
| 
								 | 
							
								        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'
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Returns
							 | 
						||
| 
								 | 
							
								        -------
							 | 
						||
| 
								 | 
							
								        result : bool
							 | 
						||
| 
								 | 
							
								            Return True on success, false otherwise.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Notes
							 | 
						||
| 
								 | 
							
								        -----
							 | 
						||
| 
								 | 
							
								        Each NumPy module exposes `test` in its namespace to run all tests for
							 | 
						||
| 
								 | 
							
								        it. For example, to run all tests for numpy.lib:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        >>> np.lib.test() #doctest: +SKIP
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Examples
							 | 
						||
| 
								 | 
							
								        --------
							 | 
						||
| 
								 | 
							
								        >>> result = np.lib.test() #doctest: +SKIP
							 | 
						||
| 
								 | 
							
								        ...
							 | 
						||
| 
								 | 
							
								        1023 passed, 2 skipped, 6 deselected, 1 xfailed in 10.39 seconds
							 | 
						||
| 
								 | 
							
								        >>> result
							 | 
						||
| 
								 | 
							
								        True
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        import pytest
							 | 
						||
| 
								 | 
							
								        import warnings
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        module = sys.modules[self.module_name]
							 | 
						||
| 
								 | 
							
								        module_path = os.path.abspath(module.__path__[0])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # setup the pytest arguments
							 | 
						||
| 
								 | 
							
								        pytest_args = ["-l"]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # offset verbosity. The "-q" cancels a "-v".
							 | 
						||
| 
								 | 
							
								        pytest_args += ["-q"]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        with warnings.catch_warnings():
							 | 
						||
| 
								 | 
							
								            warnings.simplefilter("always")
							 | 
						||
| 
								 | 
							
								            # Filter out distutils cpu warnings (could be localized to
							 | 
						||
| 
								 | 
							
								            # distutils tests). ASV has problems with top level import,
							 | 
						||
| 
								 | 
							
								            # so fetch module for suppression here.
							 | 
						||
| 
								 | 
							
								            from numpy.distutils import cpuinfo
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        with warnings.catch_warnings(record=True):
							 | 
						||
| 
								 | 
							
								            # Ignore the warning from importing the array_api submodule. This
							 | 
						||
| 
								 | 
							
								            # warning is done on import, so it would break pytest collection,
							 | 
						||
| 
								 | 
							
								            # but importing it early here prevents the warning from being
							 | 
						||
| 
								 | 
							
								            # issued when it imported again.
							 | 
						||
| 
								 | 
							
								            import numpy.array_api
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # 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",
							 | 
						||
| 
								 | 
							
								            ]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # When testing matrices, ignore their PendingDeprecationWarnings
							 | 
						||
| 
								 | 
							
								        pytest_args += [
							 | 
						||
| 
								 | 
							
								            "-W ignore:the matrix subclass is not",
							 | 
						||
| 
								 | 
							
								            "-W ignore:Importing from numpy.matlib is",
							 | 
						||
| 
								 | 
							
								            ]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if doctests:
							 | 
						||
| 
								 | 
							
								            pytest_args += ["--doctest-modules"]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if extra_argv:
							 | 
						||
| 
								 | 
							
								            pytest_args += list(extra_argv)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if verbose > 1:
							 | 
						||
| 
								 | 
							
								            pytest_args += ["-" + "v"*(verbose - 1)]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if coverage:
							 | 
						||
| 
								 | 
							
								            pytest_args += ["--cov=" + module_path]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if label == "fast":
							 | 
						||
| 
								 | 
							
								            # not importing at the top level to avoid circular import of module
							 | 
						||
| 
								 | 
							
								            from numpy.testing import IS_PYPY
							 | 
						||
| 
								 | 
							
								            if IS_PYPY:
							 | 
						||
| 
								 | 
							
								                pytest_args += ["-m", "not slow and not slow_pypy"]
							 | 
						||
| 
								 | 
							
								            else:
							 | 
						||
| 
								 | 
							
								                pytest_args += ["-m", "not slow"]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        elif label != "full":
							 | 
						||
| 
								 | 
							
								            pytest_args += ["-m", label]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if durations >= 0:
							 | 
						||
| 
								 | 
							
								            pytest_args += ["--durations=%s" % durations]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if tests is None:
							 | 
						||
| 
								 | 
							
								            tests = [self.module_name]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        pytest_args += ["--pyargs"] + list(tests)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # run tests.
							 | 
						||
| 
								 | 
							
								        _show_numpy_info()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        try:
							 | 
						||
| 
								 | 
							
								            code = pytest.main(pytest_args)
							 | 
						||
| 
								 | 
							
								        except SystemExit as exc:
							 | 
						||
| 
								 | 
							
								            code = exc.code
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return code == 0
							 |