Python+Selenium:如何为@pytest.mark.parametrize传入函数并解决报错
问题分析
你遇到的AttributeError: 'function' object has no attribute 'execute_script'错误,根源在于测试收集阶段的执行时机问题:
@pytest.mark.parametrize是在pytest收集测试用例时就执行的,此时你的driverfixture还没有被实例化为WebDriver对象,传入get_images_list的driver只是一个fixture函数本身,自然没有execute_script方法。- 另外,即使能获取到元素对象,它也是绑定到特定driver实例的,跨测试用例复用会触发
StaleElementReferenceException,所以直接参数化元素对象本身不可行。
解决方案
方案一:用pytest_generate_tests动态参数化图片src
通过pytest的钩子函数,在测试运行前临时初始化driver获取所有图片的src,再将src作为参数传入测试用例,每个用例中重新定位图片并检查加载状态:
import pytest from selenium import webdriver from selenium.webdriver.common.by import By def pytest_generate_tests(metafunc): # 仅当测试用例包含image_src参数时才执行参数化 if "image_src" in metafunc.fixturenames: # 临时初始化driver获取图片src列表 temp_driver = webdriver.Chrome() temp_driver.get("https://openweathermap.org/") # 提取所有图片的src并去重 image_srcs = temp_driver.execute_script( "return Array.from(document.querySelectorAll('img')).map(img => img.src)" ) unique_srcs = list(set(image_srcs)) temp_driver.quit() # 动态生成测试参数 metafunc.parametrize("image_src", unique_srcs) @pytest.fixture(scope="module") def driver(): # 正式测试用的driver实例 driver = webdriver.Chrome() yield driver driver.quit() def test_image_load(driver, image_src): driver.get("https://openweathermap.org/") try: # 根据src定位图片元素 image = driver.find_element(By.CSS_SELECTOR, f"img[src='{image_src}']") # 检查图片是否加载完成(更可靠的判断方式) is_loaded = driver.execute_script( "return arguments[0].complete && arguments[0].naturalWidth > 0", image ) assert is_loaded, f"图片 {image_src} 未正常显示" except: pytest.fail(f"图片 {image_src} 不存在或加载失败")
方案二:通过fixture参数化图片src
利用fixture的params属性,结合全局fixture获取图片src列表,实现参数化:
import pytest from selenium import webdriver from selenium.webdriver.common.by import By @pytest.fixture(scope="module") def driver(): driver = webdriver.Chrome() driver.get("https://openweathermap.org/") yield driver driver.quit() @pytest.fixture(scope="module") def all_image_srcs(driver): # 获取所有图片的src并去重 srcs = driver.execute_script( "return Array.from(document.querySelectorAll('img')).map(img => img.src)" ) return list(set(srcs)) @pytest.fixture(scope="function", params=[]) def image_src(request, all_image_srcs): # 将src列表作为参数传递给每个测试用例 request.param = all_image_srcs return request.param def test_image_load(driver, image_src): image = driver.find_element(By.CSS_SELECTOR, f"img[src='{image_src}']") is_loaded = driver.execute_script( "return arguments[0].complete && arguments[0].naturalWidth > 0", image ) assert is_loaded, f"图片 {image_src} 未正常显示"
关键注意点
- 不要参数化WebElement对象:元素实例与特定driver实例绑定,跨用例复用必然触发过期元素异常。
- 图片加载判断用
complete+naturalWidth:比单纯判断width/height更可靠,能区分图片是否真的加载完成(而非占位宽高)。
内容的提问来源于stack exchange,提问作者zaelcovsky
相关产品推荐
相关产品推荐

