Pytest入门系列之pytest的内置fixture

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 自动提供临时路径

常见 pytest 内置 fixture

内置 fixture 作用
request 访问当前测试信息
monkeypatch 修改环境变量、类、函数等
tmpdir 提供临时目录(py.path.local 对象)
tmp_pathd 提供临时目录(pathlib.Path 对象)
capsys 捕获 sys.stdoutsys.stderr
caplog 捕获日志输出
recwarn 捕获 warnings 警告
pytestconfig 捕获 pytest 命令行参数
doctest_namespace 修改 doctest_namespace 运行环境

request

request:访问当前测试信息

📌 requestpytest 内置的 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}") # 如果是类方法,返回类名;否则返回 None
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:创建临时目录

📌 tmpdirtmp_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 # 检查 `-v` 选项是否启用

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,后面遇见继续补充!


Pytest入门系列之pytest的内置fixture
https://dreamshao.github.io/2025/03/20/pytest入门系列4/
作者
Yun Shao
发布于
2025年3月20日
许可协议