Python pytest 的 fixture 作用域问题

xwwr · 2024年12月19日 · 最后由 xwwr 回复于 2025年01月03日 · 3632 次阅读

conftest.py 文件部分

@pytest.fixture(scope="session")
def driver(request):
    marker = request.node.get_closest_marker("device_name")
    if marker is None:
        raise ValueError("必须为测试用例提供一个 'device_name' 参数")

测试方法为

@pytest.mark.device_name("emulator_1")
@pytest.mark.usefixtures("driver")
class TestLogin:
    def test_login(self, driver):

向大家请教一下,当我把@pytest.fixture(scope="session") 的 scope 调整为 class 时,driver 中 marker 能正确获取到测试用例传值 emulator_1,但是我修改为 session 后,此处 device_name 则为空了。这是因为什么呀?小白请指教

共收到 4 条回复 时间 点赞

当你将 @pytest.fixture 的 scope 设置为 "session" 时,意味着这个 fixture 将在整个测试会话期间只初始化一次。这意味着无论你运行多少个测试类或测试函数,driver fixture 只会在第一次需要它的时候被调用,并且它的状态会被保留直到整个测试会话结束。
而当你把 scope 设置为 "class" 时,fixture 每当遇到一个新的测试类时就会重新初始化一次。也就是说,对于每个测试类,都会创建一个新的 driver 实例。
在你的例子中,device_name marker 是通过 request.node.get_closest_marker("device_name") 获取的。request.node 在不同的 scope 下代表不同的对象:
当 scope="session" 时,request.node 指的是整个测试会话的根节点。
当 scope="class" 时,request.node 指的是当前的测试类。
因此,如果你使用 scope="session",那么在 driver fixture 被首次调用时,它实际上是在尝试从整个测试会话的根节点获取 device_name marker。然而,device_name marker 是在具体的测试类(TestLogin)上定义的,所以根节点上并不存在这个 marker,这就是为什么你会看到它是空的。

可以看一下这个系列视频,fixture 讲的比较清楚了:

xwwr #3 · 2025年01月03日 Author
fox 回复

谢谢,看明白了!

xwwr #4 · 2025年01月03日 Author
虫师 回复

!!好的,讲的好

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册