pytest 测试框架学习(3):pytest.approx

时间:2022-07-24
本文章向大家介绍pytest 测试框架学习(3):pytest.approx,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

pytest.approx

  • 前言
  • 含义
  • 使用
    • 单数
    • 元祖
    • 字典
    • numpy 数组:
    • 相对误差 和 绝对误差
  • 进阶

前言

经过 API 我们已经了解到 pytest 中包括的 API 大致内容,接下来我们详细看看 Functions 中的 pytest.approx

含义

approx:在一定误差范围内断言两个数字(或两组数字)相等。 源码如图:

使用

我们知道计算机运算浮点数的复杂性,我们直观认为相等的而实际上并不相等;

单数

0.1 + 0.2 == 0.3
# 我们认为上方计算出来结果进行比对返回应该是 True,而实际返回
False

而 approx 可以帮我们解决这个问题:

from pytest import approx
0.1 + 0.2 == approx(0.3)

元祖

(0.1 + 0.2, 0.2 + 0.4) == approx((0.3, 0.6))

字典

{'a': 0.1 + 0.2, 'b': 0.2 + 0.4} == approx({'a': 0.3, 'b': 0.6})

numpy 数组:

numpy 介绍和使用

import numpy as np
np.array([0.1, 0.2]) + np.array([0.2, 0.4]) == approx(np.array([0.3, 0.6]))

如果 numpy 数组中结果一致,则可以直接填入一个标量,如:

import numpy as np
np.array([0.1, 0.2]) + np.array([0.2, 0.1]) == approx(0.3)

相对误差 和 绝对误差

默认情况,approx() 使用的为 相对误差,误差的范围是 1e-6 也就是百万分之一。

  1. 指定相对误差:
  1. 只指定绝对误差,不指定相对误差,则根据绝对误差来进行比较:
  1. 指定两个,只要满足其中一个,则认为是相等的:

进阶

主要包括:

  1. 其他方法的浮点数比较与 pytest.approx() 的区别: 技术能力有限,这里不做细致说明,贴出官网源码。
math.isclose(a, b, rel_tol=1e-9, abs_tol=0.0)
"""
- ``math.isclose(a, b, rel_tol=1e-9, abs_tol=0.0)``:  True if the relative
      tolerance is met w.r.t. either ``a`` or ``b`` or if the absolute
      tolerance is met.  Because the relative tolerance is calculated w.r.t.
      both ``a`` and ``b``, this test is symmetric (i.e.  neither ``a`` nor
      ``b`` is a "reference value").  You have to specify an absolute tolerance
      if you want to compare to ``0.0`` because there is no tolerance by
      default.  Only available in python>=3.5.  `More information...`__
      __ https://docs.python.org/3/library/math.html#math.isclose
"""

numpy.isclose(a, b, rtol=1e-5, atol=1e-8)
"""
- ``numpy.isclose(a, b, rtol=1e-5, atol=1e-8)``: True if the difference
      between ``a`` and ``b`` is less that the sum of the relative tolerance
      w.r.t. ``b`` and the absolute tolerance.  Because the relative tolerance
      is only calculated w.r.t. ``b``, this test is asymmetric and you can
      think of ``b`` as the reference value.  Support for comparing sequences
      is provided by ``numpy.allclose``.  `More information...`__
      __ http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.isclose.html
"""

unittest.TestCase.assertAlmostEqual(a, b)
"""
- ``unittest.TestCase.assertAlmostEqual(a, b)``: True if ``a`` and ``b``
      are within an absolute tolerance of ``1e-7``.  No relative tolerance is
      considered and the absolute tolerance cannot be changed, so this function
      is not appropriate for very large or very small numbers.  Also, it's only
      available in subclasses of ``unittest.TestCase`` and it's ugly because it
      doesn't follow PEP8.  `More information...`__
      __ https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertAlmostEqual
"""

a == pytest.approx(b, rel=1e-6, abs=1e-12)
"""
- ``a == pytest.approx(b, rel=1e-6, abs=1e-12)``: True if the relative
      tolerance is met w.r.t. ``b`` or if the absolute tolerance is met.
      Because the relative tolerance is only calculated w.r.t. ``b``, this test
      is asymmetric and you can think of ``b`` as the reference value.  In the
      special case that you explicitly specify an absolute tolerance but not a
      relative tolerance, only the absolute tolerance is considered.
"""
  1. 运算符比较
"""
In order to avoid inconsistent behavior, ``TypeError`` is
       raised for ``>``, ``>=``, ``<`` and ``<=`` comparisons.
       The example below illustrates the problem::

           assert approx(0.1) > 0.1 + 1e-10  # calls approx(0.1).__gt__(0.1 + 1e-10)
           assert 0.1 + 1e-10 > approx(0.1)  # calls approx(0.1).__lt__(0.1 + 1e-10)

       In the second example one expects ``approx(0.1).__le__(0.1 + 1e-10)``
       to be called. But instead, ``approx(0.1).__lt__(0.1 + 1e-10)`` is used to
       comparison. This is because the call hierarchy of rich comparisons
       follows a fixed behavior. `More information...`__

       __ https://docs.python.org/3/reference/datamodel.html#object.__ge__
"""

说明:本篇参考官网并加入自己些许理解翻译而来,觉得有用,可以点赞和赞赏哦(^ v ^),谢谢支持;如果有不足地方,可留言评论。后续将继续更新。