@@ -82,8 +82,8 @@ Run tests using your favourite IDE such as `vscode`_ or `pycharm`_
82
82
Writing your own tests
83
83
''''''''''''''''''''''
84
84
85
- If you are writing a package that you'd like to become part of NumPy,
86
- please write the tests as you develop the package .
85
+ If you are writing code that you'd like to become part of NumPy,
86
+ please write the tests as you develop your code .
87
87
Every Python module, extension module, or subpackage in the NumPy
88
88
package directory should have a corresponding ``test_<name>.py `` file.
89
89
Pytest examines these files for test methods (named ``test* ``) and test
@@ -114,27 +114,41 @@ a test class::
114
114
with pytest.raises(ValueError, match='.*some matching regex.*'):
115
115
...
116
116
117
- Within these test methods, ``assert `` and related functions are used to test
118
- whether a certain assumption is valid. If the assertion fails, the test fails.
117
+ Within these test methods, the ``assert `` statement or a specialized assertion
118
+ function is used to test whether a certain assumption is valid. If the
119
+ assertion fails, the test fails. Common assertion functions include:
120
+
121
+ - :func: `numpy.testing.assert_equal ` for testing exact elementwise equality
122
+ between a result array and a reference,
123
+ - :func: `numpy.testing.assert_allclose ` for testing near elementwise equality
124
+ between a result array and a reference (i.e. with specified relative and
125
+ absolute tolerances), and
126
+ - :func: `numpy.testing.assert_array_less ` for testing (strict) elementwise
127
+ ordering between a result array and a reference.
128
+
129
+ Note that these assertion functions only compare the numerical values of the
130
+ arrays. Consider adding separate ``assert `` statements regarding the array
131
+ dtype and shape (when the reference is a scalar). Note that
119
132
``pytest `` internally rewrites the ``assert `` statement to give informative
120
- output when it fails, so should be preferred over the legacy variant
133
+ output when it fails, so it should be preferred over the legacy variant
121
134
``numpy.testing.assert_ ``. Whereas plain ``assert `` statements are ignored
122
135
when running Python in optimized mode with ``-O ``, this is not an issue when
123
136
running tests with pytest.
124
137
125
138
Similarly, the pytest functions :func: `pytest.raises ` and :func: `pytest.warns `
126
139
should be preferred over their legacy counterparts
127
140
:func: `numpy.testing.assert_raises ` and :func: `numpy.testing.assert_warns `,
128
- since the pytest variants are more broadly used and allow more explicit
129
- targeting of warnings and errors when used with the `` match `` regex.
130
-
141
+ which are more broadly used. These versions also accept a `` match ``
142
+ parameter, which should always be used to precisely target the intended
143
+ warning or error.
131
144
132
145
Note that ``test_ `` functions or methods should not have a docstring, because
133
146
that makes it hard to identify the test from the output of running the test
134
147
suite with ``verbose=2 `` (or similar verbosity setting). Use plain comments
135
- (``# ``) if necessary.
148
+ (``# ``) to describe the intent of the test and help the unfamiliar reader to
149
+ interpret the code.
136
150
137
- Also since much of NumPy is legacy code that was
151
+ Also, since much of NumPy is legacy code that was
138
152
originally written without unit tests, there are still several modules
139
153
that don't have tests yet. Please feel free to choose one of these
140
154
modules and develop tests for it.
@@ -209,9 +223,21 @@ automatically via special arguments. For example, the special argument name
209
223
Parametric tests
210
224
----------------
211
225
212
- One very nice feature of testing is allowing easy testing across a range
213
- of parameters - a nasty problem for standard unit tests. Use the
214
- ``pytest.mark.parametrize `` decorator.
226
+ One very nice feature of ``pytest `` is the ease of testing across a range
227
+ of parameter values using the ``pytest.mark.parametrize `` decorator. For example,
228
+ suppose you wish to test ``linalg.solve `` for all combinations of three
229
+ array sizes and two data types::
230
+
231
+ @pytest.mark.parametrize('dimensionality', [3, 10, 25])
232
+ @pytest.mark.parametrize('dtype', [np.float32, np.float64])
233
+ def test_solve(dimensionality, dtype):
234
+ np.random.seed(842523)
235
+ A = np.random.random(size=(dimensionality, dimensionality)).astype(dtype)
236
+ b = np.random.random(size=dimensionality).astype(dtype)
237
+ x = np.linalg.solve(A, b)
238
+ eps = np.finfo(dtype).eps
239
+ assert_allclose(A @ x, b, rtol=eps*1e2, atol=0)
240
+ assert x.dtype == np.dtype(dtype)
215
241
216
242
Doctests
217
243
--------
@@ -294,46 +320,6 @@ found and run::
294
320
Tips & Tricks
295
321
'''''''''''''
296
322
297
- Creating many similar tests
298
- ---------------------------
299
-
300
- If you have a collection of tests that must be run multiple times with
301
- minor variations, it can be helpful to create a base class containing
302
- all the common tests, and then create a subclass for each variation.
303
- Several examples of this technique exist in NumPy; below are excerpts
304
- from one in `numpy/linalg/tests/test_linalg.py
305
- <https://github.com/numpy/numpy/blob/main/numpy/linalg/tests/test_linalg.py> `__::
306
-
307
- class LinalgTestCase:
308
- def test_single(self):
309
- a = array([[1., 2.], [3., 4.]], dtype=single)
310
- b = array([2., 1.], dtype=single)
311
- self.do(a, b)
312
-
313
- def test_double(self):
314
- a = array([[1., 2.], [3., 4.]], dtype=double)
315
- b = array([2., 1.], dtype=double)
316
- self.do(a, b)
317
-
318
- ...
319
-
320
- class TestSolve(LinalgTestCase):
321
- def do(self, a, b):
322
- x = linalg.solve(a, b)
323
- assert_allclose(b, dot(a, x))
324
- assert imply(isinstance(b, matrix), isinstance(x, matrix))
325
-
326
- class TestInv(LinalgTestCase):
327
- def do(self, a, b):
328
- a_inv = linalg.inv(a)
329
- assert_allclose(dot(a, a_inv), identity(asarray(a).shape[0]))
330
- assert imply(isinstance(a, matrix), isinstance(a_inv, matrix))
331
-
332
- In this case, we wanted to test solving a linear algebra problem using
333
- matrices of several data types, using ``linalg.solve `` and
334
- ``linalg.inv ``. The common test cases (for single-precision,
335
- double-precision, etc. matrices) are collected in ``LinalgTestCase ``.
336
-
337
323
Known failures & skipping tests
338
324
-------------------------------
339
325
0 commit comments