Selenium Pytest出现ValueError: setup未生成值的问题排查
问题:Pytest Class级Fixture抛出
ValueError: setup did not yield a value的原因与修复方案 问题背景
我有多个基于Selenium+Python+Pytest的测试套件(如test_invoice.py、test_admin.py等),均使用同一个class级别的setup fixture。通过Docker执行测试的命令如下:
python -m pytest -v -s --capture=tee-sys --html=report.html --self-contained-html test_invoice.py test_admin.py test_cash.py
setup fixture代码如下:
@pytest.fixture(scope='class') def setup(request): try: options = webdriver.ChromeOptions() options.add_argument("--window-size=1920,1080") options.add_argument("--start-maximized") options.add_argument('--headless') options.add_argument('--ignore-certificate-errors') driver = webdriver.Chrome(options=options) request.cls.driver = driver driver.delete_all_cookies() driver.get(TestData_common.BASE_URL) yield driver.quit() except WebDriverException as e: print('App seems to be down...> ', e) @pytest.mark.usefixtures("setup") @pytest.mark.incremental class Test_app: def test_001_login(self): assert TestData_common.URL_FOUND, "UAT seems to be down.." self.loginPage = LoginPage(self.driver) self.loginPage.do_click_agree_button() assert TestData_common.AGREE_BTN_FOUND, "Unable to click AGREE button.." self.driver.maximize_window() print('Successfully clicked AGREE button') time.sleep(2)
测试过程中偶尔会抛出如下错误:
request = <SubRequest 'setup' for <Function test_001_login>> kwargs = {'request': <SubRequest 'setup' for <Function test_001_login>>} def call_fixture_func( fixturefunc: "_FixtureFunc[FixtureValue]", request: FixtureRequest, kwargs ) -> FixtureValue: if is_generator(fixturefunc): fixturefunc = cast( Callable[..., Generator[FixtureValue, None, None]], fixturefunc ) generator = fixturefunc(**kwargs) try: fixture_result = next(generator) except StopIteration: > raise ValueError(f"{request.fixturename} did not yield a value") from None E **ValueError: setup did not yield a value**
原因分析
这个错误的核心是fixture的try/except代码块范围错误:
- 你把
yield和driver.quit()都放在了try块内,而except块直接跟在try外部。 - 当
try块内的代码(如Chrome初始化、页面访问)抛出WebDriverException时,程序会直接跳转到except块执行打印逻辑,随后函数直接结束,完全没走到yield语句。 - Pytest的生成器类型fixture要求必须执行到
yield,否则会被判定为“未产生值”,进而抛出ValueError。
修复方案
调整try/except的范围,确保无论是否发生异常,yield都会被执行,同时正确清理资源:
修复后的fixture代码
@pytest.fixture(scope='class') def setup(request): driver = None try: options = webdriver.ChromeOptions() options.add_argument("--window-size=1920,1080") options.add_argument("--start-maximized") options.add_argument('--headless') options.add_argument('--ignore-certificate-errors') driver = webdriver.Chrome(options=options) request.cls.driver = driver driver.delete_all_cookies() driver.get(TestData_common.BASE_URL) yield # 确保此语句一定会被执行 except WebDriverException as e: print('App seems to be down...> ', e) # 可选:重新抛出异常,让测试直接标记为失败 raise finally: # 无论是否异常,都关闭浏览器,避免资源泄漏 if driver is not None: driver.quit()
关键修改点
- 预初始化driver为None:避免finally块引用未定义的变量
- 缩小try块范围:仅将可能抛出
WebDriverException的初始化代码放在try内,yield放在try块末尾 - 用finally块清理资源:不管是否发生异常,都会执行浏览器关闭逻辑,防止进程残留
- 可选重新抛出异常:如果希望fixture异常时直接终止测试,可在except块中添加
raise,否则测试会继续执行,可能引发更多错误
内容的提问来源于stack exchange,提问作者Ram
相关产品推荐
相关产品推荐

