Pytest入门系列之pytest的fixture

Pytest入门系列之pytest的fixture

pytest 是 Python 最流行的测试框架之一,而 fixture 是 pytest 提供的 强大测试前后置机制,用于管理测试依赖、初始化测试环境和清理资源。

什么是 fixture?

在 pytest 中,fixture 是一种特殊的函数,用于 在测试开始前进行准备工作,并在测试结束后进行清理。
它可以用于:
✅ 创建测试数据
✅ 数据库连接
✅ 初始化 WebDriver(Selenium)
✅ 文件操作
✅ 清理资源

📌 基本语法

1
2
3
4
5
6
7
8
9
import pytest

@pytest.fixture
def sample_data():
return {"name": "Alice", "age": 25}

def test_sample(sample_data):
assert sample_data["name"] == "Alice"

🔍 解析:

@pytest.fixture 让 sample_data() 成为一个 fixture。
test_sample() 通过参数 自动接收 sample_data() 的返回值。
运行时 pytest 自动调用 fixture,无需手动传参。

fixture 的作用域 (scope)

fixture 默认 作用于每个测试函数(function 级别),但 pytest 允许我们通过 scope 控制

1
2
3
4
@pytest.fixture(scope="function")  # 默认,每个测试函数执行一次
@pytest.fixture(scope="class") # 每个测试类执行一次
@pytest.fixture(scope="module") # 每个模块执行一次
@pytest.fixture(scope="session") # 整个测试执行一次

📌 示例:不同作用域的 fixture

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import pytest

@pytest.fixture(scope="session")
def db_connection():
print("\n🔗 连接数据库")
yield
print("\n❌ 关闭数据库")

@pytest.fixture(scope="function")
def test_user():
print("\n👤 创建测试用户")
yield {"username": "test_user"}
print("\n🗑️ 删除测试用户")

def test_example_1(db_connection, test_user):
print("✅ 运行 test_example_1")

def test_example_2(db_connection, test_user):
print("✅ 运行 test_example_2")

🔍 解析:

db_connection() scope=”session” → 整个测试运行一次。
test_user() scope=”function” → 每个测试函数运行一次。

🔄 运行顺序

1
pytest test_example.py -s  # -s 让 print 输出可见
1
2
3
4
5
6
7
8
9
10
🔗 连接数据库      # 只执行一次(session 级别)
👤 创建测试用户 # 每个测试函数执行一次
✅ 运行 test_example_1
🗑️ 删除测试用户

👤 创建测试用户
✅ 运行 test_example_2
🗑️ 删除测试用户
❌ 关闭数据库 # 只执行一次(session 级别)

yield 语句管理 fixture

fixture 不仅可以提供数据,还可以执行“前后置”逻辑,yield 允许在 测试结束后执行清理工作。

📌 示例:使用 yield 进行资源清理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import pytest

@pytest.fixture
def open_file():
file = open("test_file.txt", "w")
print("\n📂 打开文件")
yield file # 让测试函数使用 file
print("\n❌ 关闭文件")
file.close()

def test_write_file(open_file):
open_file.write("Hello, pytest fixture!")
assert open_file.closed is False

def test_file_closed(open_file):
assert open_file.closed is False

🔍 运行流程

测试开始前:执行 print(“\n📂 打开文件”) 并打开文件。
测试运行中:yield 让测试函数使用 file。
测试结束后:执行 file.close() 关闭文件。

autouse=True 自动应用 fixture

📌 如果不想手动传入 fixture,可以使用 autouse=True 自动应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import pytest

@pytest.fixture(autouse=True)
def setup_teardown():
print("\n🔧 测试前置操作")
yield
print("\n🗑️ 测试后置清理")

def test_case_1():
print("✅ 运行 test_case_1")

def test_case_2():
print("✅ 运行 test_case_2")

🔍 运行输出

1
2
3
4
5
6
7
🔧 测试前置操作
✅ 运行 test_case_1
🗑️ 测试后置清理

🔧 测试前置操作
✅ 运行 test_case_2
🗑️ 测试后置清理

📌 适用于

日志记录
数据库连接
全局资源初始化

conftest.py 让 fixture 适用于所有测试

如果 fixture 在多个测试文件中通用,可以放入 conftest.py,这样所有测试都会自动找到它。

📌 conftest.py

1
2
3
4
5
6
import pytest

@pytest.fixture
def global_data():
return {"project": "pytest"}

📌 在 test_sample.py 里直接使用

1
2
3
def test_global(global_data):
assert global_data["project"] == "pytest"

📌 这样可以在任何测试文件里使用 global_data,无需 import。

fixture 之间的依赖

fixture 可以互相依赖:

1
2
3
4
5
6
7
8
9
10
11
12
@pytest.fixture
def user_data():
return {"username": "alice"}

@pytest.fixture
def authenticated_user(user_data):
user_data["authenticated"] = True
return user_data

def test_auth_user(authenticated_user):
assert authenticated_user["authenticated"] is True

📌 运行时 authenticated_user 会先调用 user_data,实现依赖注入。

参数化 fixture

📌 有时,我们需要对 fixture 传递多个值,可以用 params 参数

1
2
3
4
5
6
7
@pytest.fixture(params=["admin", "editor", "viewer"])
def user_role(request):
return request.param # 获取参数值

def test_user_role(user_role):
assert user_role in ["admin", "editor", "viewer"]

📌 运行时,pytest 会 自动为 user_role 生成 3 组测试:

1
2
3
test_user_role[admin]  ✅
test_user_role[editor] ✅
test_user_role[viewer] ✅

组合多个 fixture

1
2
3
4
def test_multiple_fixture(user_data, authenticated_user):
assert authenticated_user["username"] == "alice"
assert authenticated_user["authenticated"] is True

📌 pytest 会自动解析依赖,先执行 user_data,再执行 authenticated_user。

总结

功能 关键特性
fixture 基础 @pytest.fixture 定义
作用域 (scope) "function", "class", "module", "session"
pytest test_sample.py::test_func 运行指定测试函数
yield 清理资源 yield 之后执行清理
自动应用 autouse=True
conftest.py 共享 fixture
参数化 fixture params=[...]

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