1"""

2 Pytest test running.

3

4 This module implements the ``test()`` function for NumPy modules. The usual

5 boiler plate for doing that is to put the following in the module

6``__init__.py`` file::

7

8 from numpy._pytesttester import PytestTester

9 test = PytestTester(__name__)

10 del PytestTester

11

12

13 Warnings filtering and other runtime settings should be dealt with in the

14``pytest.ini`` file in the numpy repo root. The behavior of the test depends on

15 whether or not that file is found as follows:

16

17* ``pytest.ini`` is present (develop mode)

18 All warnings except those explicitly filtered out are raised as error.

19* ``pytest.ini`` is absent (release mode)

20 DeprecationWarnings and PendingDeprecationWarnings are ignored, other

21 warnings are passed through.

22

23 In practice, tests run from the numpy repo are run in develop mode. That

24 includes the standard ``python runtests.py`` invocation.

25

26 This module is imported by every numpy subpackage, so lies at the top level to

27 simplify circular import issues. For the same reason, it contains no numpy

28 imports at module scope, instead importing numpy within function calls.

29"""

30 import sys

31 import os

32

33__all__ = ['PytestTester']

34

35

36 def _show_numpy_info():

37 import numpy as np

38

39 print("NumPy version %s" % np.__version__)

40 relaxed_strides = np.ones((10, 1), order="C").flags.f_contiguous

41 print("NumPy relaxed strides checking option:", relaxed_strides)

42 info = np.lib.utils._opt_info()

43 print("NumPy CPU features: ", (info if info else 'nothing enabled'))

44

45

46 class PytestTester:

47 """

48 Pytest test runner.

49

50 A test function is typically added to a package's __init__.py like so::

51

52 from numpy._pytesttester import PytestTester

53 test = PytestTester(__name__).test

54 del PytestTester

55

56 Calling this test function finds and runs all tests associated with the

57 module and all its sub-modules.

58

59 Attributes

60 ----------

61 module_name : str

62 Full path to the package to test.

63

64 Parameters

65 ----------

66 module_name : module name

67 The name of the module to test.

68

69 Notes

70 -----

71 Unlike the previous ``nose``-based implementation, this class is not

72 publicly exposed as it performs some ``numpy``-specific warning

73 suppression.

74

75 """

76 def __init__(self, module_name):

77 self.module_name = module_name

78

79 def __call__(self, label='fast', verbose=1, extra_argv=None,

80 doctests=False, coverage=False, durations=-1, tests=None):

81 """

82 Run tests for module using pytest.

83

84 Parameters

85 ----------

86 label : {'fast', 'full'}, optional

87 Identifies the tests to run. When set to 'fast', tests decorated

88 with `pytest.mark.slow` are skipped, when 'full', the slow marker

89 is ignored.

90 verbose : int, optional

91 Verbosity value for test outputs, in the range 1-3. Default is 1.

92 extra_argv : list, optional

93 List with any extra arguments to pass to pytests.

94 doctests : bool, optional

95 .. note:: Not supported

96 coverage : bool, optional

97 If True, report coverage of NumPy code. Default is False.

98 Requires installation of (pip) pytest-cov.

99 durations : int, optional

100 If < 0, do nothing, If 0, report time of all tests, if > 0,

101 report the time of the slowest `timer` tests. Default is -1.

102 tests : test or list of tests

103 Tests to be executed with pytest '--pyargs'

104

105 Returns

106 -------

107 result : bool

108 Return True on success, false otherwise.

109

110 Notes

111 -----

112 Each NumPy module exposes `test` in its namespace to run all tests for

113 it. For example, to run all tests for numpy.lib:

114

115 >>> np.lib.test() #doctest: +SKIP

116

117 Examples

118 --------

119 >>> result = np.lib.test() #doctest: +SKIP

120 ...

121 1023 passed, 2 skipped, 6 deselected, 1 xfailed in 10.39 seconds

122 >>> result

123 True

124

125 """

126 import pytest

127 import warnings

128

129 module = sys.modules[self.module_name]

130 module_path = os.path.abspath(module.__path__[0])

131

132 # setup the pytest arguments

133 pytest_args = ["-l"]

134

135 # offset verbosity. The "-q" cancels a "-v".

136 pytest_args += ["-q"]

137

138 with warnings.catch_warnings():

139 warnings.simplefilter("always")

140 # Filter out distutils cpu warnings (could be localized to

141 # distutils tests). ASV has problems with top level import,

142 # so fetch module for suppression here.

143 from numpy.distutils import cpuinfo

144

145 with warnings.catch_warnings(record=True):

146 # Ignore the warning from importing the array_api submodule. This

147 # warning is done on import, so it would break pytest collection,

148 # but importing it early here prevents the warning from being

149 # issued when it imported again.

150 import numpy.array_api

151

152 # Filter out annoying import messages. Want these in both develop and

153 # release mode.

154 pytest_args += [

155 "-W ignore:Not importing directory",

156 "-W ignore:numpy.dtype size changed",

157 "-W ignore:numpy.ufunc size changed",

158 "-W ignore::UserWarning:cpuinfo",

159 ]

160

161 # When testing matrices, ignore their PendingDeprecationWarnings

162 pytest_args += [

163 "-W ignore:the matrix subclass is not",

164 "-W ignore:Importing from numpy.matlib is",

165 ]

166

167 if doctests:

168 pytest_args += ["--doctest-modules"]

169

170 if extra_argv:

171 pytest_args += list(extra_argv)

172

173 if verbose > 1:

174 pytest_args += ["-" + "v"*(verbose - 1)]

175

176 if coverage:

177 pytest_args += ["--cov=" + module_path]

178

179 if label == "fast":

180 # not importing at the top level to avoid circular import of module

181 from numpy.testing import IS_PYPY

182 if IS_PYPY:

183 pytest_args += ["-m", "not slow and not slow_pypy"]

184 else:

185 pytest_args += ["-m", "not slow"]

186

187 elif label != "full":

188 pytest_args += ["-m", label]

189

190 if durations >= 0:

191 pytest_args += ["--durations=%s" % durations]

192

193 if tests is None:

194 tests = [self.module_name]

195

196 pytest_args += ["--pyargs"] + list(tests)

197

198 # run tests.

199 _show_numpy_info()

200

201 try:

202 code = pytest.main(pytest_args)

203 except SystemExit as exc:

204 code = exc.code

205

206 return code == 0