自动化测试|Pytest中的fixture装饰器详解
pytest是Python生态中最流行的自动化测试框架,它通过简洁的语法、强大的功能(如fixture、参数化、插件扩展等)和丰富的插件生态,帮助开发者高效完成单元测试、集成测试和端到端测试。fixture是pytest框架中最核心、最强大的功能之一,它提供了一种优雅的方式来管理测试依赖项(如数据库连接、测试数据、API客户端等),实现了测试代码的模块化和复用。
1fixture基础概念
1. fixture的作用
依赖注入:自动将资源(如数据库连接)注入到测试函数中
资源管理:统一管理测试资源的创建和清理
复用性:多个测试用例可以共享同一个fixture
2. 基本语法
import pytest @pytest.fixture def fixture_name(): # 初始化代码 resource = create_resource() yield resource # 返回资源给测试用例使用 # 清理代码(测试完成后执行) resource.cleanup()2fixture核心特性
1. 作用域控制
通过scope参数控制fixture的生命周期:
function(默认):每个测试函数执行一次
class:每个测试类执行一次
module:每个Python模块执行一次
package:每个包执行一次
session:整个测试会话执行一次
@pytest.fixture(scope="module") def shared_resource(): return create_expensive_resource()2. 自动使用
通过autouse=True让fixture自动执行,无需显式调用
@pytest.fixture def db_connection(): return connect_to_database() @pytest.fixture def user_repo(db_connection): return UserRepository(db_connection)3. 依赖其他fixture
fixture可以依赖其他fixture
@pytest.fixture def db_connection(): return connect_to_database() @pytest.fixture def user_repo(db_connection): return UserRepository(db_connection)3fixture使用案例
1)API客户端初始化
import pytest import requests @pytest.fixture(scope="module") def api_client(): client = requests.Session() client.base_url = "https://api.example.com" client.headers = {"Authorization": "Bearer test_token"} yield client # 整个测试模块共享同一个客户端 client.close() # 模块测试完成后关闭 def test_get_user(api_client): response = api_client.get("/users/1") assert response.status_code == 200 assert response.json()["name"] == "Alice"2)Web浏览器实例管理(结合Selenium)
import pytest from selenium import webdriver @pytest.fixture(scope="class") def browser(): driver = webdriver.Chrome() driver.implicitly_wait(10) yield driver # 整个测试类共享同一个浏览器实例 driver.quit() # 类测试完成后关闭浏览器 class TestWebLogin: def test_login(self, browser): browser.get("https://example.com/login") browser.find_element("#username").send_keys("admin") browser.find_element("#password").send_keys("secret") browser.find_element("#submit").click() assert "Dashboard" in browser.title4fixture高级技巧
1)动态fixture参数化
@pytest.fixture(params=["sqlite", "mysql", "postgres"]) def database(request): return create_db_connection(request.param) def test_db_operations(database): assert database.execute("SELECT 1") == 12)多个fixture组合
@pytest.fixture def auth_token(): return "test_token_123" @pytest.fixture def authenticated_client(api_client, auth_token): api_client.headers["Authorization"] = f"Bearer {auth_token}" return api_client def test_protected_endpoint(authenticated_client): response = authenticated_client.get("/protected") assert response.status_code == 200