智障能学会编程吗 2025-08-13 11:38 采纳率: 0%
浏览 8

pytest中fixture范围是session,仍然多次调用了,并且没正常teardown

当fixture的范围设置成session时,理应只调用一次浏览器,执行完全部用力后,关闭浏览器
但我遇到的问题是:打开浏览器1后,执行第一条用例成功后,又新打开一个浏览器2,执行第二条用例成功后,关闭浏览器2,浏览器1不会自动关闭。
单独执行两条用例,都是正常的,浏览器均能自动打开关闭。

conftest中的两个fixture,一个是打开关闭浏览器,一个是登录登出用户

img

注册的实现

img

注册用例

img

添加购物车实现

img

添加购物车的用例

img

  • 写回答

4条回答 默认 最新

  • 檀越@新空间 2025-08-13 11:42
    关注

    上午好☀️☀️☀️️
    本答案参考通义千问

    在使用 pytest 时,如果将 fixture 的作用范围设置为 session,理论上该 fixture 应该在整个测试会话中只被初始化一次,并且在所有测试用例结束后才进行清理(teardown)。但你提到的问题是:即使设置了 scope="session",仍然多次调用了浏览器,并且没有正常关闭

    这可能是因为以下原因导致的:


    问题分析

    1. fixture 没有正确设置 scope
    2. 多个 fixture 同时控制浏览器生命周期
    3. 某些用例或 fixture 被重复调用
    4. 测试框架未正确识别 session 级别 fixture 的 teardown

    解决方案

    1. 确保 fixture 正确设置 scope 为 "session"

    检查你的 conftest.py 中的 fixture 定义,确认是否使用了 @pytest.fixture(scope="session")。例如:

    import pytest
    from selenium import webdriver
    
    @pytest.fixture(scope="session")
    def browser():
        driver = webdriver.Chrome()
        yield driver
        driver.quit()
    

    注意: 如果你在其他地方又定义了一个同名的 fixture,或者在不同的模块中定义了 browser,可能会导致冲突。


    2. 避免多个 fixture 控制同一个资源

    如果你有两个 fixture 分别控制浏览器和用户登录,可能会导致资源被重复初始化。例如:

    # conftest.py
    @pytest.fixture(scope="session")
    def browser():
        # 初始化浏览器
        yield driver
        driver.quit()
    
    @pytest.fixture(scope="session")
    def login(browser):
        # 登录逻辑
        yield user
        # 不应该在这里关闭浏览器!
    

    错误点: login fixture 可能会重新初始化浏览器,或者破坏 browser fixture 的生命周期。


    3. 确保 fixture 仅被调用一次

    你可以通过打印日志来验证 fixture 是否真的只执行了一次:

    @pytest.fixture(scope="session")
    def browser():
        print("Initializing browser (only once)")
        driver = webdriver.Chrome()
        yield driver
        print("Closing browser")
        driver.quit()
    

    运行测试后查看输出日志,确认是否只出现一次初始化和关闭信息。


    4. 使用 autouse=True 时需谨慎

    如果你使用了 autouse=True,确保它不会被误触发多次。例如:

    @pytest.fixture(scope="session", autouse=True)
    def setup_browser():
        # 这个 fixture 会被自动调用
        driver = webdriver.Chrome()
        yield driver
        driver.quit()
    

    注意: 如果这个 fixture 被多个测试用例引用,可能导致重复初始化。


    5. 避免在测试用例中手动启动浏览器

    不要在测试用例中直接创建浏览器实例,而是依赖 fixture 来管理。例如:

    def test_add_to_cart(browser):
        browser.get("http://example.com")
        # 添加购物车操作
    

    推荐的代码结构示例

    # conftest.py
    import pytest
    from selenium import webdriver
    
    @pytest.fixture(scope="session")
    def browser():
        print("Initializing browser (only once)")
        driver = webdriver.Chrome()
        yield driver
        print("Closing browser")
        driver.quit()
    
    @pytest.fixture(scope="session")
    def login(browser):
        # 假设这是登录操作
        print("Logging in")
        # 登录逻辑
        yield "user"
        print("Logging out")
    
    # 测试用例
    def test_add_to_cart(browser, login):
        browser.get("http://example.com")
        # 执行添加购物车操作
        assert True
    
    def test_register_user(browser, login):
        browser.get("http://example.com/register")
        # 执行注册操作
        assert True
    

    总结

    | 问题 | 解决方案 | |------|----------| | fixture scope 设置不正确 | 使用 @pytest.fixture(scope="session") | | 多个 fixture 控制同一个资源 | 避免重复初始化,统一由一个 fixture 管理 | | fixture 被重复调用 | 检查是否有多个同名 fixture 或 autouse=True 导致重复加载 | | teardown 未执行 | 确保 yield 后的代码在 session 结束时执行 |


    最终建议

    • 使用 print() 或日志记录来验证 fixture 的执行次数。
    • 只保留一个 session 级别的 browser fixture,并确保它被所有需要它的测试用例所引用。
    • 避免在测试用例中直接初始化浏览器,而应依赖 fixture。

    如你愿意提供具体的 conftest.py 和测试用例代码,我可以进一步帮你定位问题。

    评论

报告相同问题?

问题事件

  • 创建了问题 8月13日