目录

测试

在本节中,您将

  • 编写一个测试来验证代码的正确性。

如果您已经了解 pytest,请查看我们更高级的 pytest 指南

您应该立即添加一个测试,当细节还记忆犹新的时候。编写测试可以让您在进行未来改进时有信心,任何意外的更改或损坏都不会被忽视。编写测试也往往鼓励您编写模块化、可重用的代码,因为这样更容易测试。

编写一些测试

为测试创建一个目录。我们建议将其放在 src 目录旁边。

mkdir tests

创建一个文件来存放您的第一个测试。文件名应以 test_ 开头。

touch tests/test_snell.py

您的包目录结构现在应该如下所示

example
├── noxfile.py
├── pyproject.toml
├── src
│   └── example
│       ├── __init__.py
│       └── rescale.py
└── tests
    └── test_rescale.py

您也可能会看到一些 __pycache__ 目录,其中包含在调用您的包时生成的已编译 Python 字节码。您可以忽略它们。

tests/test_snell.py 中编写一些示例测试,例如以下内容

# contents of tests/test_snell.py

import numpy as np
import pytest

from example.refraction import snell


# For any indexes, a ray normal to the surface should not bend.
# We'll try a couple different combinations of indexes....


def test_perpendicular_1():
    actual = snell(0, 2.00, 3.00)
    assert actual == pytest.approx(0)


def test_perpendicular_2():
    actual = snell(0, 3.00, 2.00)
    assert actual == pytest.approx(0)


def test_air_water():
    n_air, n_water = 1.00, 1.33
    actual = snell(np.pi / 4, n_air, n_water)
    expected = 0.5605584137424605
    assert actual == pytest.approx(expected)

需要注意的事情

  • 将多个断言语句放在一个测试中很诱人,但尽量避免这样做。您应该为每个要检查的行为创建一个单独的测试,因为 pytest 只会报告第一个测试,这会让您对失败情况有一个不完整的了解。这通常被称为排列-操作-断言模式。
  • 在比较浮点数(与整数相反)时,您不应该测试精确的相等性。 pytest.approx 支持模糊比较并支持 NumPy 数组。
  • 所有测试模块和函数的名称必须以 test 开头。(否则,它们将不会被我们将在下面使用的自动测试运行器拾取。)这允许您也编写不是测试的帮助函数。

运行测试

科学 Python 包通常使用名为 pytest 的程序来运行其测试并报告成功和失败。安装 pytest

pip install pytest

运行 pytest

pytest

这将遍历我们包中所有以单词 test 开头的目录和文件,并收集所有名称也以 test 开头的函数。 pytest 运行每个函数。如果没有抛出异常,则测试通过。

输出应该类似于以下内容

======================================== test session starts ========================================
platform darwin -- Python 3.6.4, pytest-3.6.2, py-1.5.4, pluggy-0.6.0
benchmark: 3.1.1 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
rootdir: /private/tmp/test11/example, inifile:
plugins: pep8-1.0.6, lazy-fixture-0.3.0, forked-0.2, benchmark-3.1.1
collected 1 item

example/tests/test_snell.py ..                                                                 [100%]

===================================== 2 passed in 0.02 seconds ======================================

pytest 的输出是可定制的。常用的命令行参数包括

  • -v 详细输出。可以给出两次。
  • -x 在第一个失败的测试时停止。非常适合长跟踪。
  • -s 显示输出到 stdout/stderr(例如,print 的输出)。默认情况下,它是隐藏的。
  • -k EXPRESSION 通过模式匹配测试名称来过滤测试。
  • --lf 仅运行上次运行失败的测试(last fail)。

有关更多信息,请咨询 pytest 文档。有关更高级的 pytest 建议,请查看我们的 pytest 指南