Assert that two numbers (or two sets of numbers) are equal to each other within some tolerance. Due to the :std:doc:`tutorial/floatingpoint`, numbers that we would intuitively expect to be equal are not always so:: >>> 0.1 + 0.2 == 0.3 False This problem is commonl
(expected, rel=None, abs=None, nan_ok: bool = False)
| 516 | |
| 517 | |
| 518 | def approx(expected, rel=None, abs=None, nan_ok: bool = False) -> ApproxBase: |
| 519 | """Assert that two numbers (or two sets of numbers) are equal to each other |
| 520 | within some tolerance. |
| 521 | |
| 522 | Due to the :std:doc:`tutorial/floatingpoint`, numbers that we |
| 523 | would intuitively expect to be equal are not always so:: |
| 524 | |
| 525 | >>> 0.1 + 0.2 == 0.3 |
| 526 | False |
| 527 | |
| 528 | This problem is commonly encountered when writing tests, e.g. when making |
| 529 | sure that floating-point values are what you expect them to be. One way to |
| 530 | deal with this problem is to assert that two floating-point numbers are |
| 531 | equal to within some appropriate tolerance:: |
| 532 | |
| 533 | >>> abs((0.1 + 0.2) - 0.3) < 1e-6 |
| 534 | True |
| 535 | |
| 536 | However, comparisons like this are tedious to write and difficult to |
| 537 | understand. Furthermore, absolute comparisons like the one above are |
| 538 | usually discouraged because there's no tolerance that works well for all |
| 539 | situations. ``1e-6`` is good for numbers around ``1``, but too small for |
| 540 | very big numbers and too big for very small ones. It's better to express |
| 541 | the tolerance as a fraction of the expected value, but relative comparisons |
| 542 | like that are even more difficult to write correctly and concisely. |
| 543 | |
| 544 | The ``approx`` class performs floating-point comparisons using a syntax |
| 545 | that's as intuitive as possible:: |
| 546 | |
| 547 | >>> from pytest import approx |
| 548 | >>> 0.1 + 0.2 == approx(0.3) |
| 549 | True |
| 550 | |
| 551 | The same syntax also works for sequences of numbers:: |
| 552 | |
| 553 | >>> (0.1 + 0.2, 0.2 + 0.4) == approx((0.3, 0.6)) |
| 554 | True |
| 555 | |
| 556 | Dictionary *values*:: |
| 557 | |
| 558 | >>> {'a': 0.1 + 0.2, 'b': 0.2 + 0.4} == approx({'a': 0.3, 'b': 0.6}) |
| 559 | True |
| 560 | |
| 561 | ``numpy`` arrays:: |
| 562 | |
| 563 | >>> import numpy as np # doctest: +SKIP |
| 564 | >>> np.array([0.1, 0.2]) + np.array([0.2, 0.4]) == approx(np.array([0.3, 0.6])) # doctest: +SKIP |
| 565 | True |
| 566 | |
| 567 | And for a ``numpy`` array against a scalar:: |
| 568 | |
| 569 | >>> import numpy as np # doctest: +SKIP |
| 570 | >>> np.array([0.1, 0.2]) + np.array([0.2, 0.1]) == approx(0.3) # doctest: +SKIP |
| 571 | True |
| 572 | |
| 573 | By default, ``approx`` considers numbers within a relative tolerance of |
| 574 | ``1e-6`` (i.e. one part in a million) of its expected value to be equal. |
| 575 | This treatment would lead to surprising results if the expected value was |