8000 Merge pull request #24667 from mdhaber/gh23283 · numpy/numpy@08fbb43 · GitHub
[go: up one dir, main page]

Skip to content

Commit 08fbb43

Browse files
authored
Merge pull request #24667 from mdhaber/gh23283
2 parents 085665c + 8741c01 commit 08fbb43

File tree

1 file changed

+39
-53
lines changed

1 file changed

+39
-53
lines changed

doc/TESTS.rst

Lines changed: 39 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ Run tests using your favourite IDE such as `vscode`_ or `pycharm`_
8282
Writing your own tests
8383
''''''''''''''''''''''
8484

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.
8787
Every Python module, extension module, or subpackage in the NumPy
8888
package directory should have a corresponding ``test_<name>.py`` file.
8989
Pytest examines these files for test methods (named ``test*``) and test
@@ -114,27 +114,41 @@ a test class::
114114
with pytest.raises(ValueError, match='.*some matching regex.*'):
115115
...
116116

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
119132
``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
121134
``numpy.testing.assert_``. Whereas plain ``assert`` statements are ignored
122135
when running Python in optimized mode with ``-O``, this is not an issue when
123136
running tests with pytest.
124137

125138
Similarly, the pytest functions :func:`pytest.raises` and :func:`pytest.warns`
126139
should be preferred over their legacy counterparts
127140
: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.
131144

132145
Note that ``test_`` functions or methods should not have a docstring, because
133146
that makes it hard to identify the test from the output of running the test
134147
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.
136150

137-
Also since much of NumPy is legacy code that was
151+
Also, since much of NumPy is legacy code that was
138152
originally written without unit tests, there are still several modules
139153
that don't have tests yet. Please feel free to choose one of these
140154
modules and develop tests for it.
@@ -209,9 +223,21 @@ automatically via special arguments. For example, the special argument name
209223
Parametric tests
210224
----------------
211225

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)
215241

216242
Doctests
217243
--------
@@ -294,46 +320,6 @@ found and run::
294320
Tips & Tricks
295321
'''''''''''''
296322

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-
337323
Known failures & skipping tests
338324
-------------------------------
339325

0 commit comments

Comments
 (0)
0