Python中有许多测试框架,但其中最受欢迎的就是PyTest。PyTest是一个强大而灵活的测试框架,它提供了许多先进的功能,可以让你的测试更加简洁、易读。
一、PyTest 简介
PyTest是一个开源的Python测试框架,用于编写简单而丰富的测试套件。它的功能特性包括:参数化、设置/拆解函数、假对象和钩子函数等。PyTest也被设计用来支持大型的测试集合,特别是适合进行回归测试。
二、PyTest 示例
接下来,我将通过以下10个示例,详细介绍如何使用PyTest。
1. 基础测试
PyTest的测试是通过编写函数并使用assert关键字进行断言的。以下是一个简单的测试示例
def test_addition():
assert 1 + 1 == 2
2. 测试异常
如果你希望一个特定的异常被抛出,可以使用pytest.raises
上下文管理器:
import pytest
def test_zero_division():
with pytest.raises(ZeroDivisionError):
1 / 0
3. 参数化测试
如果你有多组输入和期望的输出,可以使用pytest.mark.parametrize
装饰器:
import pytest
@pytest.mark.parametrize("a,b,expected", [(1, 2, 3), (4, 5, 9), (7, 8, 15)])
def test_addition(a, b, expected):
assert a + b == expected
4. 使用setup和teardown
对于需要前置和后置操作的测试,你可以使用setup和teardown函数:
def setup_function(function):
if function == test_needs_resource_a:
setup_resource_a()
def teardown_function(function):
if function == test_needs_resource_a:
teardown_resource_a()
def test_needs_resource_a():
assert use_resource_a()
5. 使用fixtures
PyTest的fixtures功能允许你定义一些设置代码,这些代码可以被多个测试函数重用:
import pytest
@pytest.fixture
def resource_a():
setup_resource_a()
yield use_resource_a()
teardown_resource_a()
def test_needs_resource_a(resource_a):
assert resource_a
6. 使用mocks
你可以使用PyTest的unittest.mock
模块创建假的对象,模拟函数或对象的行为:
from unittest.mock import MagicMock
def test_with_mock():
my_mock = MagicMock(return_value=3)
assert my_mock(1, 2, 3) == 3
my_mock.assert_called_once_with(1, 2, 3)
7. 测试私有函数
虽然一般来说我们应该避免测试私有函数,但有时这也是有用的:
def test__private_function():
from my_module import _private_function
assert _private_function(1, 2) == 3
在这个示例中,我们测试了一个名为_private_function的私有函数。这个函数接受两个参数并返回它们的和。我们使用了assert语句来确认返回的结果是否与预期的结果相符。注意,这个例子仅作为示例,实际上我们应尽量避免对私有函数进行单独测试,因为它们的实现可能会随着时间而改变。在大多数情况下,我们应该专注于测试公共接口,这样可以保证即使实现细节发生改变,测试仍然有效。
8. 跳过某些测试
如果有些测试你不希望执行,你可以使用pytest.mark.skip
或pytest.mark.skipif
来跳过这些测试:
import pytest
@pytest.mark.skip(reason="This test is currently being debugged.")
def test_in_debugging():
assert 1 + 1 == 2
9. 使用pytest的命令行参数
PyTest提供了许多命令行参数,可以帮助你更有效地运行测试。例如,你可以使用-k
参数来运行名称匹配某个模式的测试:
pytest -k "addition"
10. 分组测试
你可以使用pytest.mark来给你的测试分组:
import pytest
@pytest.mark.slow
def test_slow_function():
# This is a slow test...
pass
@pytest.mark.fast
def test_fast_function():
# This is a fast test...
pass
然后你可以只运行某个分组的测试:
pytest -m slow
11. 使用assert
进行多种条件检查
PyTest的assert
可以被用来进行多种条件检查。例如,我们可以使用assert
来检查是否一个值在一个列表中:
def test_in_list():
assert 1 in [1, 2, 3]
12. 使用xfail
标记预期失败的测试
如果你知道某个测试目前不能通过,但你仍然希望执行它并记录结果,可以使用pytest.mark.xfail
:
import pytest
@pytest.mark.xfail(reason="This test is expected to fail.")
def test_failing():
assert 1 == 2
13. 使用capsys
fixture捕获标准输出
如果你的函数会打印到标准输出,你可以使用capsys
fixture来捕获这些输出,然后在你的测试中进行检查:
def test_print_output(capsys):
print("Hello")
captured = capsys.readouterr()
assert captured.out == "Hello\n"
14. 使用tmp_path
fixture创建临时文件
如果你的测试需要创建临时文件,你可以使用tmp_path
fixture:
def test_create_file(tmp_path):
d = tmp_path / "sub"
d.mkdir()
p = d / "hello.txt"
p.write_text("Hello, World!")
assert p.read_text() == "Hello, World!"
15. 与doctest结合
如果你的函数或者模块包含doctest,PyTest可以直接运行这些doctest:
def add(a, b):
"""
This function adds two numbers.
>>> add(1, 2)
3
"""
return a + b