当前位置: 首页 > news >正文

Selenium WebUI 自动化“避坑”指南——从常用 API 到 10 大高频问题

目录

一、为什么 90% 的 UI 自动化脚本活不过 3 个月?

二、Selenium必会 API 速查

三、实践

四、10 大高频异常“症状 → 病因 → 处方”

五、可复用的工具函数

六、面试高频追问(附标准答案)

一、为什么 90% 的 UI 自动化脚本活不过 3 个月?

  • 元素定位“玄学”——今天跑通、明天 404

  • 等待策略“拍脑袋”——隐式、显式、sleep 乱用一通

  • 验证码、iframe、多窗口、动态 ID……一步一坑

本文主要关于常见Selenium应用API和常见问题处理。


二、Selenium必会 API 速查

  •     定位元素
    • element = 浏览器对象.find_element(by=By.定位方式,value="属性值")
  • 常见操作

    • 模拟点击:element.click()

    • 模拟输入:element.send_keys()

    • 模拟清除:element.clear()

  • 浏览器操作

    • 浏览器最大化driver.maximize_window()

    • 浏览器刷新driver.refresh()

    • 浏览器前进:driver.forward()

    • 浏览器后退:driver.back()

    • 获取标题:driver.title

    • 获取网页地址:driver.current_url

  • 页面元素判断

    • 元素是否可见:element.is_displayed()

    • 元素是否可用:element.is_enabled()

    • 元素是否选中element.is_selected ()

  • 滚动条处理

    • 定义js字符串:js = "window.scrollTo(0,1000)"

    • 执行js字符串:driver.execute_script(js)

  • 弹出框处理

    • 自定义弹框:通过元素定位后直接处理

    • JS弹框

      • alert:告警框

      • confirm:确认框

      • prompt:普通提示框

alert= driver.switch_to.alert #获取弹出框对象,三种弹出框,在对象获取的时候都一样
alert.text #获取弹出框文本
alert.accept() #接受弹出框,弹出框处理方法
alert.dismiss() #取消弹出框,弹出框处理方法,确认框没有取消按钮,取消方法一样生效
  • 鼠标操作

#导包
from selenium.webdriver import Actionchains#实例化鼠标对象
action = ActionChains(driver)#调用鼠标方法,element表示元素对象
action.move_to_element(element) #鼠标悬停action.context_click(element) #鼠标右击action.double_click(element) #鼠标双击action.drag_and_drop(source, target) #拖拽#执行鼠标操作,调用鼠标方法并不会去执行鼠标操作,必须调用perform才会执行
action.perform()
  • 下拉框操作

    Select类:只适用于HTML原生态的下拉框,即<select>+<option>的组合标签

    #1.导包
    from selenium.webdriver.support.select import Select#2.创建select对象
    select = Select(element)#3.选择选项
    select.select_by_index(index) #根据下标select.select_by_value(value) #根据选项value属性值select.select_by_visible_text(text) #根据选项文本

三、实践

场景推荐写法(Selenium 4 新语法)一句话提醒
元素定位driver.find_element(By.CSS_SELECTOR, "#username")拒绝 find_element_by_* 老语法,PyCharm 已标黄
等待元素可见WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, "//button[text()='立即购买']")))显式等待优先,隐式等待只做“兜底”
下拉框Select(driver.find_element(By.ID, "city")).select_by_visible_text("上海")仅适用于原生 <select>,自定义组件请用点击组合
鼠标悬停ActionChains(driver).move_to_element(menu).perform()99% 的“悬浮才显示”坑都能用这一行解决
滚动到元素driver.execute_script("arguments[0].scrollIntoView({block:'center'});", element)滚动到中心,避免被固定 header 遮挡
新窗口driver.switch_to.window(driver.window_handles[-1])句柄按出现顺序压栈,-1 永远是最新窗口
frame 切回driver.switch_to.default_content()嵌套 frame 请一层一层切,别“跳级”
截图取证driver.save_screenshot(f"./evidence/{case_name}_{timestamp}.png")目录提前建好,png 无损且 Jenkins 可预览
高亮标记driver.execute_script("arguments[0].setAttribute('style', 'border:3px solid red');", elem)失败截图前高亮,一眼看出哪个元素出错

四、10 大高频异常“症状 → 病因 → 处方”

症状病因定位清单(按概率排序)处方(复制即用)
NoSuchElementException1. 动态 ID / 随机 class

 
1. 改用 CSS “稳态”属性,[data-testid="loginBtn"]
 
ElementClickIntercepted被蒙层/吐司/固定 header 遮挡滚动到中心 + JS 点击:driver.execute_script("arguments[0].click()", elem)
StaleElementReferenceDOM 整片刷新(Vue/React)重新定位 + 显式等待,禁止把 WebElement 当“长期变量”
TimeoutException显式等待条件写错用 EC.presence_of_element_located 还是 visibility_of_element_located?前者只判 DOM,后者判可视
验证码阻挡公司无白名单① 万能验证码 8888 配置
 
文件上传弹窗不是网页元素直接 send_keys(绝对路径) 到 <input type=file>,AutoIt 已过时
下载弹窗Chrome 每次询问启动参数加:prefs = {"download.default_directory": "/tmp", "download.prompt_for_download": False}
内存暴涨未关窗口、日志堆积每条用例结束 driver.quit() + 日志轮转
多线程串包全局静态 driver用 threading.local() 或 pytest-xdist 的 --dist=loadgroup
360/安全软件拦截WebDriver 被识别加启动参数:--disable-blink-features=AutomationControlled + 替换 cdc_ 变量(Selenium-Stealth)

五、可复用的工具函数

# utils/selenium_helper.py
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutExceptionclass SeleniumHelper:def __init__(self, driver):self.driver = driverdef wait_and_click(self, locator: tuple, timeout=10):"""等待元素可见并点击"""WebDriverWait(self.driver, timeout).until(EC.visibility_of_element_located(locator)).click()def wait_iframe_and_switch(self, iframe_locator: tuple, timeout=10):"""等待 iframe 出现并切换进入"""WebDriverWait(self.driver, timeout).until(EC.frame_to_be_available_and_switch_to_it(iframe_locator))def back_to_default_content(self):self.driver.switch_to.default_content()def upload_file(self, input_locator: tuple, file_path: str):"""原生上传"""self.driver.find_element(*input_locator).send_keys(file_path)def set_cookies_from_dict(self, cookies: dict):"""一键注入登录态,跳过验证码"""self.driver.get("https://xxx.com")  # 先访问同域空白页for k, v in cookies.items():self.driver.add_cookie({"name": k, "value": v})self.driver.refresh()

六、面试高频追问(附标准答案)

  1. 隐式等待与显式等待能否同时用?
    答:可以,但隐式等待会拖慢显式等待的轮询效率,Selenium 官方建议二选一;生产环境统一用显式等待。

  2. 如何判断元素是否在 iframe?
    答:Chrome DevTools → Elements → 搜索 //iframe,看目标节点是否被 <iframe> 包裹;脚本里捕获 NoSuchElementException 后重试 driver.switch_to.frame()

  3. 验证码到底要不要自动化?
    答:QA 职责是“测试业务主路径”,不是“破解验证码”。优先让开发配置万能验证码或关闭验证码;次选注入 Cookie;OCR 识别成本最高,ROI 最低。


文章转载自:

http://Uv7Lrti8.gtdnq.cn
http://cK51DugO.gtdnq.cn
http://CDFJWlHO.gtdnq.cn
http://GMHb7bmj.gtdnq.cn
http://kZburDj0.gtdnq.cn
http://cpWYZ5ek.gtdnq.cn
http://6GOIb8RD.gtdnq.cn
http://DXEas9pp.gtdnq.cn
http://iBwdcige.gtdnq.cn
http://gWj2gro6.gtdnq.cn
http://r5sAGgEf.gtdnq.cn
http://RvnvWq60.gtdnq.cn
http://XEalfhbA.gtdnq.cn
http://bgT4cJTA.gtdnq.cn
http://ttDJHhLu.gtdnq.cn
http://IJcxm50O.gtdnq.cn
http://3GN6Kiv3.gtdnq.cn
http://reHTsXTy.gtdnq.cn
http://FWZiwO8k.gtdnq.cn
http://Dl6ZDNYg.gtdnq.cn
http://sbtSlxOc.gtdnq.cn
http://QpoUlaF2.gtdnq.cn
http://koV3RPHQ.gtdnq.cn
http://5KFdYnMR.gtdnq.cn
http://GljQ4klA.gtdnq.cn
http://SNcBh657.gtdnq.cn
http://MAZppUnU.gtdnq.cn
http://RlazYPVJ.gtdnq.cn
http://Kb4fJ4E7.gtdnq.cn
http://TsIT9YI7.gtdnq.cn
http://www.dtcms.com/a/364713.html

相关文章:

  • ASP.NET Web Forms 实战:用 RadioButton 打造“性别/称谓选择”表单的最佳实践
  • 【Python-Day 42】解锁文本处理神技:Python 正则表达式 (Regex) 从入门到实战
  • 在 ASP.NET 8 WebAPI 中使用不同的提供程序验证多个令牌(Token)及常见问题解答
  • 前端开发基础必备——操作系统、计网、数据结构与算法编译原理
  • SpringBoot Web 入门指南:从零搭建第一个SpringBoot程序
  • [TryHackMe]Oh My WebServer(nday漏洞+容器逃逸)
  • Archlinux KDE 下 Fcitx5 输入法的配置与美化
  • 重新测试所有AI代码生成器(2025年更新):GPT-5 vs Claude 4.1 vs Gemini 2.5 Pro——为何“赢家”仍取决于你的技术栈
  • 一文掌握Redisson分布式锁
  • 天然苏打水生产的原水抽取与三重除菌的3D模拟开发实战
  • 编辑器vim(Linux)
  • Chrome 插件开发入门:从基础到实践
  • 美团龙猫AI修正的二分法提取xlsx的sheet.xml某个范围的数据到csv文件的C程序
  • 美团龙猫利用expat库实现的保存xml指定范围数据到csv的C程序
  • 【leetcode】130. 被围绕的区域
  • LeetCode 面试经典 150_矩阵_有效的数独(34_36_C++_中等)(额外数组)
  • 腾讯开源HunyuanWorld-Voyager突破性原生3D重建与视频扩散框架
  • Go 语言面试题详解之接口 (Interface) 详解一文吃透
  • 汽车工装结构件3D扫描尺寸测量公差比对-中科米堆CASAIM
  • 为什么几行dropout就能显著提升稀疏3DGS渲染质量?
  • 网格图--Day04--网格图DFS--2684. 矩阵中移动的最大次数,1254. 统计封闭岛屿的数目,130. 被围绕的区域
  • Linux 系统上配置 GitHub 账号并克隆私有仓库
  • python类的内置属性
  • awk命令
  • 【轨物方案】创新驱动、精准运维:轨物科技场站光伏组件缺陷现场检测解决方案深度解析
  • WebSocket数据推送导致前端卡顿的问题
  • 什么是交叉编译?
  • Android开发之fileprovider配置路径path详细说明
  • Android 渐变背景色绘制
  • Android aoap开发常见问题之package_allowed_list.txt导致的编译报错