_pytesttester.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. """
  2. Pytest test running.
  3. This module implements the ``test()`` function for NumPy modules. The usual
  4. boiler plate for doing that is to put the following in the module
  5. ``__init__.py`` file::
  6. from numpy._pytesttester import PytestTester
  7. test = PytestTester(__name__)
  8. del PytestTester
  9. Warnings filtering and other runtime settings should be dealt with in the
  10. ``pytest.ini`` file in the numpy repo root. The behavior of the test depends on
  11. whether or not that file is found as follows:
  12. * ``pytest.ini`` is present (develop mode)
  13. All warnings except those explicitly filtered out are raised as error.
  14. * ``pytest.ini`` is absent (release mode)
  15. DeprecationWarnings and PendingDeprecationWarnings are ignored, other
  16. warnings are passed through.
  17. In practice, tests run from the numpy repo are run in develop mode. That
  18. includes the standard ``python runtests.py`` invocation.
  19. This module is imported by every numpy subpackage, so lies at the top level to
  20. simplify circular import issues. For the same reason, it contains no numpy
  21. imports at module scope, instead importing numpy within function calls.
  22. """
  23. import sys
  24. import os
  25. __all__ = ['PytestTester']
  26. def _show_numpy_info():
  27. from numpy.core._multiarray_umath import (
  28. __cpu_features__, __cpu_baseline__, __cpu_dispatch__
  29. )
  30. import numpy as np
  31. print("NumPy version %s" % np.__version__)
  32. relaxed_strides = np.ones((10, 1), order="C").flags.f_contiguous
  33. print("NumPy relaxed strides checking option:", relaxed_strides)
  34. if len(__cpu_baseline__) == 0 and len(__cpu_dispatch__) == 0:
  35. enabled_features = "nothing enabled"
  36. else:
  37. enabled_features = ' '.join(__cpu_baseline__)
  38. for feature in __cpu_dispatch__:
  39. if __cpu_features__[feature]:
  40. enabled_features += " %s*" % feature
  41. else:
  42. enabled_features += " %s?" % feature
  43. print("NumPy CPU features:", enabled_features)
  44. class PytestTester:
  45. """
  46. Pytest test runner.
  47. A test function is typically added to a package's __init__.py like so::
  48. from numpy._pytesttester import PytestTester
  49. test = PytestTester(__name__).test
  50. del PytestTester
  51. Calling this test function finds and runs all tests associated with the
  52. module and all its sub-modules.
  53. Attributes
  54. ----------
  55. module_name : str
  56. Full path to the package to test.
  57. Parameters
  58. ----------
  59. module_name : module name
  60. The name of the module to test.
  61. Notes
  62. -----
  63. Unlike the previous ``nose``-based implementation, this class is not
  64. publicly exposed as it performs some ``numpy``-specific warning
  65. suppression.
  66. """
  67. def __init__(self, module_name):
  68. self.module_name = module_name
  69. def __call__(self, label='fast', verbose=1, extra_argv=None,
  70. doctests=False, coverage=False, durations=-1, tests=None):
  71. """
  72. Run tests for module using pytest.
  73. Parameters
  74. ----------
  75. label : {'fast', 'full'}, optional
  76. Identifies the tests to run. When set to 'fast', tests decorated
  77. with `pytest.mark.slow` are skipped, when 'full', the slow marker
  78. is ignored.
  79. verbose : int, optional
  80. Verbosity value for test outputs, in the range 1-3. Default is 1.
  81. extra_argv : list, optional
  82. List with any extra arguments to pass to pytests.
  83. doctests : bool, optional
  84. .. note:: Not supported
  85. coverage : bool, optional
  86. If True, report coverage of NumPy code. Default is False.
  87. Requires installation of (pip) pytest-cov.
  88. durations : int, optional
  89. If < 0, do nothing, If 0, report time of all tests, if > 0,
  90. report the time of the slowest `timer` tests. Default is -1.
  91. tests : test or list of tests
  92. Tests to be executed with pytest '--pyargs'
  93. Returns
  94. -------
  95. result : bool
  96. Return True on success, false otherwise.
  97. Notes
  98. -----
  99. Each NumPy module exposes `test` in its namespace to run all tests for
  100. it. For example, to run all tests for numpy.lib:
  101. >>> np.lib.test() #doctest: +SKIP
  102. Examples
  103. --------
  104. >>> result = np.lib.test() #doctest: +SKIP
  105. ...
  106. 1023 passed, 2 skipped, 6 deselected, 1 xfailed in 10.39 seconds
  107. >>> result
  108. True
  109. """
  110. import pytest
  111. import warnings
  112. module = sys.modules[self.module_name]
  113. module_path = os.path.abspath(module.__path__[0])
  114. # setup the pytest arguments
  115. pytest_args = ["-l"]
  116. # offset verbosity. The "-q" cancels a "-v".
  117. pytest_args += ["-q"]
  118. # Filter out distutils cpu warnings (could be localized to
  119. # distutils tests). ASV has problems with top level import,
  120. # so fetch module for suppression here.
  121. with warnings.catch_warnings():
  122. warnings.simplefilter("always")
  123. from numpy.distutils import cpuinfo
  124. # Filter out annoying import messages. Want these in both develop and
  125. # release mode.
  126. pytest_args += [
  127. "-W ignore:Not importing directory",
  128. "-W ignore:numpy.dtype size changed",
  129. "-W ignore:numpy.ufunc size changed",
  130. "-W ignore::UserWarning:cpuinfo",
  131. ]
  132. # When testing matrices, ignore their PendingDeprecationWarnings
  133. pytest_args += [
  134. "-W ignore:the matrix subclass is not",
  135. "-W ignore:Importing from numpy.matlib is",
  136. ]
  137. if doctests:
  138. raise ValueError("Doctests not supported")
  139. if extra_argv:
  140. pytest_args += list(extra_argv)
  141. if verbose > 1:
  142. pytest_args += ["-" + "v"*(verbose - 1)]
  143. if coverage:
  144. pytest_args += ["--cov=" + module_path]
  145. if label == "fast":
  146. # not importing at the top level to avoid circular import of module
  147. from numpy.testing import IS_PYPY
  148. if IS_PYPY:
  149. pytest_args += ["-m", "not slow and not slow_pypy"]
  150. else:
  151. pytest_args += ["-m", "not slow"]
  152. elif label != "full":
  153. pytest_args += ["-m", label]
  154. if durations >= 0:
  155. pytest_args += ["--durations=%s" % durations]
  156. if tests is None:
  157. tests = [self.module_name]
  158. pytest_args += ["--pyargs"] + list(tests)
  159. # run tests.
  160. _show_numpy_info()
  161. try:
  162. code = pytest.main(pytest_args)
  163. except SystemExit as exc:
  164. code = exc.code
  165. return code == 0