测试
在本节中,您将
- 编写一个测试来验证代码的正确性。
如果您已经了解 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)。