在Python中编写代码时,确保代码按预期工作是很重要的。最好的方法之一是使用单元测试,它可以帮助您检查代码的小部分(或单元)是否正常工作。
在本文中,我们将学习如何使用PyTest来编写和运行有效的单元测试,
这是Python最流行的测试框架之一。
什么是单元测试?
单元测试是小型、简单的测试,专注于检查单个函数或小段代码。它们有助于确保您的代码按预期工作,并能及早发现错误。
可以为代码的不同部分编写单元测试,例如函数、方法,甚至类。通过编写单元测试,您可以在不运行整个程序的情况下测试代码。
为什么使用PyTest?PyTest是一个流行的Python测试框架,使编写和运行测试变得简单。
它易于使用,并具有许多有用的功能,例如:
- 允许您编写简单明了的测试用例。
- 提供高级功能,如夹具、参数化测试和插件。
- 与其他测试工具和库兼容性良好。
- 生成易于阅读的测试结果和报告。
在Linux中设置PyTest
在我们开始编写测试之前,我们需要安装PyTest。如果你还没有安装PyTest,可以使用名为pip的Python包管理器来安装它。
pip install pytest
一旦安装了PyTest,你就可以开始编写测试了!
使用PyTest编写你的第一个测试
让我们先写一个简单的函数,然后为它编写测试。
步骤1:编写一个简单的函数
首先,让我们创建一个我们想要测试的Python函数。假设我们有一个将两个数字相加的函数:
# add.py def add(a, b): return a + b
这是一个简单的函数,它接受两个数字a和b,将它们相加并返回结果。
步骤2:为函数编写测试
现在,让我们为加法函数编写一个测试。在PyTest中,测试通常写在单独的文件中,这些文件通常命名为test_*.py
,以便于识别测试文件。
创建一个名为test_add.py
的新文件,并编写以下测试代码:
# test_add.py from add import add def test_add_numbers(): assert add(2, 3) == 5 assert add(-1, 1) == 0 assert add(0, 0) == 0
上述代码的解释:
- 我们从
add.py
文件中导入add
函数。 - 我们定义一个名为
test_add_numbers()
的测试函数。在PyTest中,测试函数应该以test_
开头。 - 在测试函数内部,我们使用
assert
语句来检查调用add
函数的结果是否与预期值匹配。如果assert
语句中的条件为True
,则测试通过;否则,测试失败。
步骤 3:运行测试
要运行测试,请打开您的终端并导航到包含test_add.py
文件的目录,然后运行以下命令:
pytest
PyTest将自动找到所有测试文件(以test_
开头的文件)并运行其中的测试。如果一切正常,您应该会看到如下输出:

点(.)
表示测试通过。如果有任何问题,PyTest将显示错误消息。
编写更高级的测试
现在我们知道如何编写和运行基本测试,让我们探索一些PyTest的更高级功能。
测试期望的异常
有时,您希望测试代码在出现问题时是否引发了正确的异常。您可以使用pytest.raises()
函数来实现这一点。
假设我们要测试一个将两个数字相除的函数。如果第二个数字为零(以避免除以零错误),我们希望引发异常。
这是divide
函数:
# divide.py def divide(a, b): if b == 0: raise ValueError("Cannot divide by zero") return a / b
现在,让我们为这个函数编写一个测试,以检查在尝试除以零时是否引发了ValueError
异常:
# test_divide.py from divide import divide import pytest def test_divide_numbers(): assert divide(10, 2) == 5 assert divide(-10, 2) == -5 assert divide(10, -2) == -5 def test_divide_by_zero(): with pytest.raises(ValueError): divide(10, 0)
代码解释:
- 我们添加了一个新的测试函数,名为
test_divide_by_zero()
. - 在这个函数内部,我们使用
pytest.raises(ValueError)
来检查当我们以零作为第二个参数调用除法函数时是否会引发ValueError
错误.
再次使用 pytest 命令运行测试。如果一切正常,你应该看到以下输出:

使用夹具进行设置和清理
在某些情况下,你可能需要在运行测试之前设置某些条件,或在测试完成后进行清理。 PyTest 提供了夹具来处理这个问题.
夹具是一个函数,你可以用它来设置或拆除测试条件。夹具通常用于创建对象或连接到测试所需的数据库.
以下是一个使用夹具设置临时目录以测试文件操作的示例:
# test_file_operations.py import pytest import os @pytest.fixture def temporary_directory(): temp_dir = "temp_dir" os.mkdir(temp_dir) yield temp_dir # This is where the test will run os.rmdir(temp_dir) # Cleanup after the test def test_create_file(temporary_directory): file_path = os.path.join(temporary_directory, "test_file.txt") with open(file_path, "w") as f: f.write("Hello, world!") assert os.path.exists(file_path)
代码说明:
- 我们定义了一个名为
temporary_directory
的夹具,它在测试之前创建一个临时目录,并在之后删除它. - 测试函数
test_create_file()
使用这个夹具在临时目录中创建一个文件,并检查该文件是否存在.
再次使用 pytest 命令运行测试。PyTest 将自动检测并使用夹具.
使用 Pytest 参数化你的测试
有时,你想用不同的输入运行相同的测试。 PyTest 让你可以轻松地使用参数化来实现这一点。
假设我们想要用多个数字对来测试我们的 add
函数。我们可以使用 pytest.mark.parametrize
来对不同的输入运行相同的测试,而不是为每一对写单独的测试函数。
# test_add.py import pytest from add import add @pytest.mark.parametrize("a, b, expected", [ (2, 3, 5), (-1, 1, 0), (0, 0, 0), (100, 200, 300) ]) def test_add_numbers(a, b, expected): assert add(a, b) == expected
代码说明:
- 我们使用
pytest.mark.parametrize
装饰器来定义多个输入集合(a
、b
和expected
)。 - 测试
function test_add_numbers()
将会对每一组输入运行一次。
再次使用 pytest 命令运行测试,这将会对每一组输入运行测试四次。
结论
在本文中,我们学习了如何使用 Python 编写和运行有效的单元测试,利用 PyTest 及早发现错误并确保代码按预期工作。
PyTest 使编写和运行这些测试变得简单,并且凭借其强大的功能,您可以在 Python 学习过程中处理更复杂的测试需求。
Source:
https://www.tecmint.com/unit-testing-python-code-with-pytest/