Pytest入门系列之pytest的内置fixture
pytest
提供了许多内置的 fixture
,用于处理测试执行、临时目录、参数化、标记等功能,大大简化测试编写。
什么是 pytest 内置 fixture?
在 pytest
中,fixture
是 测试前后置 机制,允许我们自动初始化资源,并在测试完成后清理资源。pytest
还提供了一些内置 fixture
,可直接使用,无需手动创建。
📌 如何使用 pytest
内置 fixture
?
只需在测试函数参数中传入 fixture
的名称,pytest
会自动提供相应的对象或功能。
无需 import
,因为它们是 pytest
预定义的 fixture
。
示例:
1 2 3
| def test_example(tmp_path): print(tmp_path)
|
常见 pytest 内置 fixture
内置 fixture |
作用 |
request |
访问当前测试信息 |
monkeypatch |
修改环境变量、类、函数等 |
tmpdir |
提供临时目录(py.path.local 对象) |
tmp_pathd |
提供临时目录(pathlib.Path 对象) |
capsys |
捕获 sys.stdout 和 sys.stderr |
caplog |
捕获日志输出 |
recwarn |
捕获 warnings 警告 |
pytestconfig |
捕获 pytest 命令行参数 |
doctest_namespace |
修改 doctest_namespace 运行环境 |
request
request:访问当前测试信息
📌 request
是 pytest
内置的 fixture
,用于获取当前测试信息,包括:
✅ 获取当前测试名称、模块、类
✅ 获取 fixture
传递的参数
✅ 动态修改 fixture
行为(动态配置 fixture)
🔹 示例 1:获取当前测试信息
request.node.name
→ 当前测试函数名
request.module
→ 当前测试模块
request.cls
→ 当前测试类(在 class 作用域内)
request.function
→ 当前测试函数对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import pytest
@pytest.fixture def my_fixture(request): print(f"\n📌 当前测试函数: {request.node.name}") print(f"📌 测试所在模块: {request.module.__name__}") print(f"📌 是否在类中运行: {request.cls}") return "Hello, Pytest!"
def test_with_request(my_fixture): print(my_fixture)
class TestExample: def test_class_method(self, my_fixture): print("✅ 运行类中的测试方法")
|
📌 运行后输出
1 2 3 4 5 6 7 8 9 10
| 📌 当前测试函数: test_with_request 📌 测试所在模块: test_example 📌 是否在类中运行: None Hello, Pytest!
📌 当前测试函数: test_class_method 📌 测试所在模块: test_example 📌 是否在类中运行: <class 'TestExample'> ✅ 运行类中的测试方法
|
🔍 解析
request.node.name
→ 获取当前测试函数名称
request.module.__name__
→ 获取当前测试所在的模块
request.cls
→ 如果测试在 class
内部,则返回类对象,否则返回 `None``
获取 fixture 传递的参数
📌 request
可以获取 fixture
传递的参数,使用 request.param
。
🔹 示例:参数化 fixture
1 2 3 4 5 6 7 8 9 10
| import pytest
@pytest.fixture(params=["admin", "editor", "viewer"]) def user_role(request): return request.param
def test_user_role(user_role): print(f"当前用户角色: {user_role}") assert user_role in ["admin", "editor", "viewer"]
|
📌 运行时,pytest
会自动为 user_role
生成 3 组测试
1 2 3 4
| test_user_role[admin] ✅ test_user_role[editor] ✅ test_user_role[viewer] ✅
|
🔍 解析
params=["admin", "editor", "viewer"]
让 fixture
自动生成多个测试
request.param
获取传递的值,每次测试 自动注入 "admin"、"editor"、"viewer"
‘
动态修改 fixture 行为
📌 request
允许我们根据 fixture
传递的参数 动态修改 fixture
行为。
🔹 示例:动态调整 fixture
逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import pytest
@pytest.fixture(params=["mysql", "postgres", "sqlite"]) def db_connection(request): db_type = request.param if db_type == "mysql": conn = "MySQL Connection" elif db_type == "postgres": conn = "PostgreSQL Connection" else: conn = "SQLite Connection"
print(f"\n🔗 连接到数据库: {conn}") yield conn print(f"\n❌ 关闭数据库连接: {conn}")
def test_database(db_connection): assert db_connection in ["MySQL Connection", "PostgreSQL Connection", "SQLite Connection"]
|
📌 运行输出
1 2 3 4 5 6 7 8 9 10 11 12
| 🔗 连接到数据库: MySQL Connection ✅ 运行 test_database ❌ 关闭数据库连接: MySQL Connection
🔗 连接到数据库: PostgreSQL Connection ✅ 运行 test_database ❌ 关闭数据库连接: PostgreSQL Connection
🔗 连接到数据库: SQLite Connection ✅ 运行 test_database ❌ 关闭数据库连接: SQLite Connection
|
🔍 解析
request.param
传递不同的数据库类型:"mysql"、"postgres"、"sqlite"
fixture
动态选择数据库连接
yield
测试结束后自动关闭数据库
结合 pytestconfig 进行动态配置
📌 request.fixturenames
获取当前测试函数使用的所有 fixture
。
🔹 示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import pytest
@pytest.fixture def fixture1(): return "fixture1_data"
@pytest.fixture def fixture2(): return "fixture2_data"
def test_fixtures(request, fixture1, fixture2): print("\n🔍 当前测试使用的 `fixture`:") for fix in request.fixturenames: print(f"- {fix}")
|
📌 运行输出
1 2 3 4 5
| 🔍 当前测试使用的 `fixture`: - request - fixture1 - fixture2
|
🔍 解析
request.fixturenames
列出当前测试使用的所有 fixture
适用于调试 fixture
依赖关系
monkeypatch:修改环境变量、类、函数
📌 monkeypatch 允许在测试中临时修改环境变量、类、函数等,测试结束后恢复。
🔹 示例 1:修改环境变量
1 2 3 4 5 6 7 8 9
| import os
def get_env_variable(): return os.getenv("MY_VAR", "default_value")
def test_env_variable(monkeypatch): monkeypatch.setenv("MY_VAR", "pytest_value") assert get_env_variable() == "pytest_value"
|
🔹 示例 2:模拟函数返回值
1 2 3 4 5 6 7 8 9
| class Database: def connect(self): return "Connected to database"
def test_mock_method(monkeypatch): db = Database() monkeypatch.setattr(db, "connect", lambda: "Mocked DB connection") assert db.connect() == "Mocked DB connection"
|
tmpdir 和 tmp_path:创建临时目录
📌 tmpdir
和 tmp_path
用于创建临时文件或目录,测试结束后自动清理。
tmpdir
返回 py.path.local
tmp_path
返回 pathlib.Path
🔹 示例 1:使用 tmpdir
1 2 3 4 5
| def test_tmpdir(tmpdir): file = tmpdir.join("test.txt") file.write("Hello, pytest!") assert file.read() == "Hello, pytest!"
|
🔹 示例 2:使用 tmp_path
1 2 3 4 5
| def test_tmp_path(tmp_path): file = tmp_path / "test.txt" file.write_text("Hello, pytest!") assert file.read_text() == "Hello, pytest!"
|
capsys:捕获 stdout 和 stderr
📌 capsys 允许捕获 print() 输出,适用于测试 CLI 程序。
🔹 示例
1 2 3 4 5 6 7 8
| def greet(): print("Hello, pytest!")
def test_greet(capsys): greet() captured = capsys.readouterr() assert captured.out == "Hello, pytest!\n"
|
📌 capsys.readouterr()
获取
captured.out
标准输出
captured.err
错误输出
caplog:捕获日志
📌 caplog
用于捕获 logging
日志。
🔹 示例
1 2 3 4 5 6 7 8 9
| import logging
def log_message(): logging.warning("This is a warning message!")
def test_log_message(caplog): log_message() assert "This is a warning message!" in caplog.text
|
recwarn:捕获 warnings
📌 recwarn
允许捕获 warnings
,用于测试警告是否正确触发。
🔹 示例
1 2 3 4 5 6 7 8 9 10
| import warnings
def deprecated_function(): warnings.warn("This function is deprecated", DeprecationWarning)
def test_warning(recwarn): deprecated_function() assert len(recwarn) == 1 assert "deprecated" in str(recwarn[0].message)
|
pytestconfig:获取 pytest 命令行参数
📌 pytestconfig
允许访问 pytest
命令行参数,例如 --verbose
。
🔹 示例
1 2 3
| def test_pytest_config(pytestconfig): assert pytestconfig.getoption("verbose") >= 0
|
doctest_namespace:修改 doctest 运行环境
📌 doctest_namespace
允许在 doctest
运行时 预定义变量。
🔹 示例
1 2 3
| @pytest.fixture(autouse=True) def add_namespace(doctest_namespace): doctest_namespace["PI"] = 3.1415926
|
📌 这样,在 doctest
中,可以直接使用PI
变量。
总结
我列举平常可能会用到的,当然还有其他的fixure,后面遇见继续补充!