1. 项目概述为什么软件测试工程师绕不开Selenium如果你是一名软件测试工程师或者正在向这个方向发展那么“Selenium”这个名字你肯定听过无数次了。它就像一个行业里的“老熟人”几乎出现在所有自动化测试的讨论和面试题里。但很多新手朋友一听到“自动化”、“框架”、“WebDriver”这些词就有点发怵感觉门槛很高文档又厚不知道从何下手。今天我就用一线测试工程师的视角带你用最快的方式“摸到”Selenium的门把手让你在一分钟内建立起最核心的认知知道它到底是什么、能干什么、以及你为什么必须会它。简单来说Selenium就是一个让你用代码来控制浏览器模拟真人操作的工具。想象一下你需要测试一个网页的登录功能。手动测试时你需要1. 打开浏览器2. 输入网址3. 找到用户名输入框输入“testuser”4. 找到密码框输入“123456”5. 点击登录按钮6. 检查页面是否跳转成功。而Selenium能让你用几行代码就自动完成这一系列动作并且可以重复执行成千上万次还能在不同的浏览器、不同的操作系统上执行。这对于需要频繁回归测试、兼容性测试的现代Web应用来说价值巨大。为什么说它是测试程序员“必会”的技能首先市场要求如此。无论是大厂还是中小公司Web自动化测试的能力几乎是测试岗位的标配而Selenium凭借其开源、免费、支持多语言Python, Java, C#, JavaScript等、支持多浏览器的特性成为了事实上的行业标准。其次它能极大提升你的测试效率和职业天花板。手动执行100个测试用例可能需要一整天还容易出错用Selenium写好脚本可能只需要喝杯咖啡的时间就能跑完解放出来的时间你可以去设计更复杂的测试场景、研究性能测试或者探索测试左移等更有价值的工作。最后学习Selenium的过程也是你理解Web应用结构HTML, CSS, JavaScript、掌握编程思维、熟悉测试框架如Pytest, TestNG的绝佳路径这些综合能力才是你职业生涯的硬通货。所以别被那些复杂的配置和术语吓到。咱们今天的目标不是成为Selenium专家而是用最短的时间帮你完成从“听说过”到“能跑起来第一个脚本”的跨越建立最直观的感性认识。收藏这篇文章当你需要动手时它可以作为你的第一份速查指南。2. Selenium核心组件与生态全解析在真正动手写代码之前花几分钟理解Selenium的“家族成员”和各司其职能让你在后续学习和排错时思路清晰不会陷入“盲人摸象”的困惑。很多人一上来就pip install selenium然后对着报错一筹莫展根本原因就是没搞懂底层依赖关系。2.1 WebDriver与浏览器对话的“翻译官”这是Selenium最核心、你必须理解的概念。WebDriver是一个遵循W3C标准的协议和一套API。你可以把它想象成一个“翻译官”。你的测试代码用Python、Java等写的说的是“人类语言”高级编程语言而Chrome、Firefox这些浏览器内核只听得懂自己的“方言”浏览器内部的调试协议如Chrome DevTools Protocol。WebDriver的工作就是居中翻译它接收你用Selenium API发出的指令如driver.find_element(By.ID, “username”).send_keys(“test”)然后将这些指令翻译成浏览器能理解的特定协议命令通过一个HTTP服务发送给浏览器。浏览器执行完操作后再把结果如页面元素的状态、截图等通过这个服务返回给WebDriverWebDriver再翻译成你的编程语言能理解的对象返回给你。这里就引出了两个关键实体浏览器驱动Driver这是WebDriver协议的具体实现是一个独立的可执行文件。比如chromedriver对应Chrome/Edgegeckodriver对应Firefox。你的代码Selenium库是通过调用这个驱动文件来控制浏览器的。所以安装Selenium库selenium包只是第一步你通常还需要下载对应浏览器版本的驱动并确保系统能找到它比如放在PATH环境变量里或者指定路径。这也是新手最容易卡住的第一步。Selenium语言绑定库这就是你通过pip install selenium或maven安装的包如seleniumfor Python,selenium-webdriverfor JavaScript。它提供了你用起来很顺手的那一套API底层会去和浏览器驱动通信。注意从Selenium 4.6版本开始官方引入了Selenium Manager。这是一个用Rust写的后台工具它会尝试自动为你下载和匹配正确版本的浏览器驱动。这大大简化了环境配置。但在某些网络环境或特定版本需求下你可能仍需手动管理驱动。了解手动配置的原理依然是排查问题的必备技能。2.2 Selenium IDE记录与回放的“快速原型工具”Selenium IDE是一个浏览器插件支持Chrome, Firefox, Edge它可以录制你在浏览器里的操作并生成可回放的测试脚本。对于完全不懂代码的测试人员或者需要快速创建一个测试用例原型时它非常有用。但你必须清楚它的定位和局限IDE生成的脚本通常比较“脆弱”依赖于录制时元素的绝对路径页面结构一变就容易失败且不易于维护和集成到持续的自动化测试流程CI/CD中。在专业的自动化测试项目中我们通常只用IDE来辅助定位元素查看元素的ID、CSS选择器等或者学习基本的Selenium命令真正的测试脚本还是倾向于用手写代码的方式因为这样更灵活、更健壮、更易于用Page Object等设计模式来组织。2.3 Selenium Grid分布式执行的“指挥中心”当你需要同时在多个不同的浏览器Chrome, Firefox, Safari和操作系统Windows, macOS, Linux上运行测试用例时手动维护多套环境是灾难。Selenium Grid就是为了解决这个问题而生的。你可以把Grid想象成一个“任务调度中心”。它有一个Hub中心节点和多个Node执行节点。Hub接收你的测试请求“我要在Windows 10的Chrome 120上跑这个测试”然后它会查找注册到它那里的、符合要求的Node将测试任务分发过去执行。Node才是真正启动浏览器、运行测试脚本的机器。这样你在一台机器上写的测试代码就可以在Grid集群中的任意节点上并行执行极大地缩短了测试总耗时完美支持了兼容性测试的需求。对于初学者前期可以不用深入Grid但要知道有这个东西存在它是企业级自动化测试基础设施的重要组成部分。2.4 与Playwright/Puppeteer的对比如何选择最近几年微软推出的Playwright和Google的Puppeteer势头很猛常被拿来和Selenium比较。这里我基于一线经验给你一个清晰的对比和选型建议特性SeleniumPlaywrightPuppeteer核心优势行业标准生态成熟支持语言和浏览器最广包括一些老旧企业浏览器。社区庞大资料极多。现代化功能强大开箱即用。自带自动等待支持移动端模拟、网络拦截、录制等高级功能API设计友好。与Chrome/Chromium深度集成性能好DevTools协议原生支持适合做爬虫、页面性能分析等。浏览器支持Chrome, Firefox, Safari, Edge, IE等。Chrome, Firefox, Safari, Edge基于Chromium。主要是Chrome/ChromiumFirefox和Safari支持是实验性的。执行速度较慢通过WebDriver协议通信。快直接使用浏览器提供的CDP等原生协议。很快直接使用CDP协议。等待机制需要显式设置等待ImplicitlyWait, WebDriverWait否则容易因元素未加载而报错。自动等待大部分操作会自动等待元素可交互脚本更健壮。需要一定的手动等待处理。上手难度中等需要处理驱动、等待等细节。较低配置简单API直观。中等更贴近底层CDP。适用场景企业级Web应用自动化测试尤其是需要支持多浏览器、多语言团队、复杂遗留系统。现代Web应用测试和自动化追求开发效率和脚本稳定性团队技术栈较新。Chromium生态下的专项任务如爬虫、PDF生成、性能监控、页面截图等。给新手的建议如果你是纯粹为了进入软件测试行业、应对面试和大多数企业项目优先学习Selenium。它是行业的“通用货币”理解它后再看Playwright会觉得很容易。如果你在一个技术栈较新的团队且主要测试现代应用Playwright是非常棒的选择。Puppeteer则更适合前端工程师或做特定Chromium相关自动化的角色。别陷入“哪个更好”的无休止争论工具是为你服务的根据你的目标和环境来选择。3. 从零开始五分钟搭建你的第一个Selenium脚本理论说再多不如亲手跑通一个例子来得实在。这里我以最流行的Python Chrome组合为例带你走通全流程。请一步步跟着操作遇到问题对照后面的“常见问题”部分排查。3.1 环境准备与安装安装Python确保你的电脑上安装了Python建议3.7及以上版本。打开命令行CMD或Terminal输入python --version检查。没有的话去Python官网下载安装。安装Selenium库这是最简单的一步。在命令行中执行pip install selenium如果速度慢可以使用国内镜像源例如pip install selenium -i https://pypi.tuna.tsinghua.edu.cn/simple处理浏览器驱动这是关键一步。你需要让Selenium能启动并控制Chrome浏览器。方案A推荐Selenium 4.6依赖Selenium Manager自动处理。 如果你安装的是较新版本的Selenium4.6以上并且Chrome浏览器已安装在默认位置那么你可能什么都不用做。Selenium Manager会在你第一次运行脚本时自动检测Chrome版本并下载匹配的chromedriver。这是最省心的方式。方案B手动更可控手动下载并配置驱动。 a.查看Chrome版本打开Chrome浏览器点击右上角三个点 - 帮助 - 关于Google Chrome记下版本号例如120.0.6099.110。 b.下载对应驱动访问ChromeDriver官网或国内镜像站下载与你的Chrome主版本号一致例如120的chromedriver。注意选择匹配你操作系统的版本Windows选win32macOS选mac64Linux选linux64。 c.放置驱动将下载的chromedriver.exeWindows文件放在一个你记得住的目录比如D:\WebDriver\。然后你需要让系统能找到它。有两种方法方法1临时在Python脚本中指定路径。方法2推荐将驱动所在目录如D:\WebDriver\添加到系统的PATH环境变量中。这样在任何地方都能调用。3.2 编写并运行你的“Hello World”脚本打开你喜欢的代码编辑器VS Code, PyCharm甚至记事本都行创建一个新文件命名为first_selenium_test.py输入以下代码from selenium import webdriver from selenium.webdriver.common.by import By import time # 1. 创建浏览器驱动对象 # 如果chromedriver已在PATH中直接这样写即可 driver webdriver.Chrome() # 如果手动指定驱动路径使用下面这行替换为你的实际路径 # driver webdriver.Chrome(executable_pathr‘D:\WebDriver\chromedriver.exe’) try: # 2. 打开目标网页 driver.get(“https://www.baidu.com”) print(f“当前页面标题是{driver.title}”) # 3. 找到搜索框并输入搜索词 # 通过查看网页源码我们知道百度首页搜索框的id是‘kw’ search_box driver.find_element(By.ID, “kw”) search_box.send_keys(“Selenium 自动化测试”) # 4. 找到“百度一下”按钮并点击 # 按钮的id是‘su’ search_button driver.find_element(By.ID, “su”) search_button.click() # 5. 等待一下让页面加载结果实际项目中应用显式等待这里用time.sleep简单演示 time.sleep(2) # 6. 验证结果例如检查页面标题或某个结果元素 print(f“搜索后页面标题是{driver.title}”) # 可以尝试查找结果页面的第一个标题这里只是示例 # first_result driver.find_element(By.CSS_SELECTOR, ‘#content_left .result h3 a’) # print(f“第一个结果是{first_result.text}”) finally: # 7. 等待几秒让你看到结果然后关闭浏览器 time.sleep(5) driver.quit()逐行解析与实操要点from selenium import webdriver导入Selenium的核心模块。from selenium.webdriver.common.by import By导入定位元素的方式By.ID, By.NAME, By.CSS_SELECTOR等这是Selenium 4的推荐写法更清晰。driver webdriver.Chrome()这行代码会启动一个全新的、干净的Chrome浏览器实例通常是无头模式不默认是有界面的你可以看到它弹出来。这个driver对象是你所有操作的入口。driver.get(url)让浏览器导航到指定的网址。这里有一个重要细节get方法会一直等待页面完全加载即浏览器onload事件触发完成才会继续执行下一行代码。但对于很多现代动态网页SPAonload事件触发时你需要的元素可能还没通过Ajax加载出来所以后续的find_element可能会失败。这就是为什么我们需要“等待”。find_element(By.ID, “kw”)在页面中查找一个元素。By.ID表示通过HTML元素的id属性来查找“kw”就是百度搜索框的id值。这是最快、最推荐的定位方式因为id通常是唯一的。如果找不到元素会抛出NoSuchElementException。send_keys(“text”)向输入框或任何可输入元素模拟键盘输入。click()模拟鼠标点击元素。time.sleep(seconds)强制让程序等待指定的秒数。这是“坏味道”的代码在正式脚本中应尽量避免。因为它是一种“固定等待”无论页面是否加载完成它都会死等拖慢测试速度。这里仅用于演示。driver.quit()关闭浏览器窗口并结束WebDriver会话释放资源。务必在最后调用否则后台可能会残留浏览器进程。我们把它放在finally块里确保即使中间代码出错浏览器也能被关闭。保存文件后在命令行中进入到这个脚本所在的目录运行python first_selenium_test.py如果一切顺利你会看到一个新的Chrome窗口自动打开访问百度输入“Selenium 自动化测试”点击搜索然后停留5秒后关闭。同时你的命令行会打印出页面标题。恭喜你你的第一个Selenium自动化脚本成功了4. 深入核心元素定位与等待策略实战精讲跑通了第一个脚本你可能觉得“不过如此”。但真正的挑战和技巧都藏在细节里。元素定位和等待机制是Selenium脚本是否稳定、健壮的关键80%的脚本错误都源于此。4.1 八种元素定位器你该用哪个find_element方法需要你告诉它“如何找到”那个元素。Selenium提供了8种主要的定位策略通过By类调用ID (By.ID)通过元素的id属性定位。优先级最高因为id在HTML中应该是唯一的。driver.find_element(By.ID, “username”)。Name (By.NAME)通过元素的name属性定位。常用于表单元素。driver.find_element(By.NAME, “password”)。Class Name (By.CLASS_NAME)通过元素的class属性定位。注意一个元素可能有多个class空格分隔这里匹配的是其中一个。driver.find_element(By.CLASS_NAME, “btn-primary”)。Tag Name (By.TAG_NAME)通过HTML标签名定位如“input”,“button”,“a”。通常一个页面有很多同标签元素所以用它定位单个元素要谨慎。driver.find_element(By.TAG_NAME, “h1”)。Link Text (By.LINK_TEXT)通过超链接的完整可见文本定位。driver.find_element(By.LINK_TEXT, “忘记密码”)。Partial Link Text (By.PARTIAL_LINK_TEXT)通过超链接的部分可见文本定位。driver.find_element(By.PARTIAL_LINK_TEXT, “忘记”)。CSS Selector (By.CSS_SELECTOR)通过CSS选择器定位。功能最强大、最灵活可以组合id、class、属性、层级关系等。driver.find_element(By.CSS_SELECTOR, “#loginForm .submit-btn”)。XPath (By.XPATH)通过XML路径语言定位。同样非常强大可以在整个HTML文档树中导航。driver.find_element(By.XPATH, “//input[id‘username’]”)。定位策略选择的心得黄金法则优先使用ID和Name其次CSS Selector万不得已再用XPath。ID/Name速度快最稳定。如果开发给元素加了好的id/name请感恩并优先使用。CSS Selector现代前端开发常用语法简洁浏览器原生支持解析速度快。对于没有id/name的复杂元素它是首选。例如要找class包含btn且type为submit的按钮By.CSS_SELECTOR, “button.btn[type‘submit’]”。XPath功能强大但速度相对慢且生成的路径可能非常“脆弱”比如/html/body/div[3]/div[2]/form/input[2]页面结构微调就会失效。应尽量避免使用绝对路径多用相对路径和属性结合如//button[text()‘登录’]。如何获取元素定位信息浏览器开发者工具F12是你的好朋友。在Elements标签页选中元素右键 - Copy - Copy selector (CSS) 或 Copy XPath。但不要完全信任自动生成的尤其是XPath经常又长又脆弱。最好自己根据HTML结构编写简洁稳定的选择器。4.2 三种等待机制告别time.sleeptime.sleep是“懒政”我们必须学会更智能的等待。隐式等待 (Implicit Wait)driver.implicitly_wait(10) # 设置一次全局生效 element driver.find_element(By.ID, “dynamicElement”)原理设置一个全局的超时时间如10秒。在查找任何一个元素时如果元素没有立即出现WebDriver会轮询DOM默认每0.5秒去查找直到找到或超时抛出异常。注意它只对find_element和find_elements方法生效。对于元素的“可点击”、“可见”等状态无效。且设置后对整个driver生命周期都有效可能会影响其他不需要等待的操作。显式等待 (Explicit Wait)这是生产环境中最推荐、最常用的方式。from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By # 创建一个等待对象最多等10秒默认每0.5秒检查一次条件 wait WebDriverWait(driver, 10) # 等待直到某个元素出现并且可见 element wait.until(EC.visibility_of_element_located((By.ID, “dynamicElement”))) # 等待直到某个元素可以被点击 button wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, “.submit-btn”))) # 等待直到页面标题包含某个文字 wait.until(EC.title_contains(“搜索结果”))原理针对某个特定的条件进行等待。你可以指定等待的最长时间、轮询频率以及要等待的条件如元素可见、可点击、存在等。只有条件满足才会继续执行否则超时抛出TimeoutException。优势精准、高效。只在需要的地方等待且条件更符合业务逻辑比如等按钮可点击了才去点而不是仅仅存在。固定等待 (time.sleep)如前所述除非在极少数调试场景下否则避免使用。最佳实践在脚本开始部分设置一个较短的隐式等待如5秒作为兜底然后在具体的、需要等待元素达到某种状态的操作前使用显式等待。显式等待的优先级更高。4.3 一个完整的登录测试案例让我们用一个更贴近实际项目的例子综合运用定位和等待from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import time driver webdriver.Chrome() driver.implicitly_wait(5) # 设置隐式等待作为基础保障 wait WebDriverWait(driver, 10) # 显式等待对象 try: driver.get(“https://example.com/login”) # 替换为你的测试登录页 # 1. 等待登录表单加载完成通过判断用户名输入框可见 username_input wait.until( EC.visibility_of_element_located((By.NAME, “username”)) ) password_input driver.find_element(By.NAME, “password”) login_button driver.find_element(By.XPATH, “//button[type‘submit’]”) # 2. 执行登录操作 username_input.send_keys(“test_user”) password_input.send_keys(“secure_password”) login_button.click() # 3. 等待登录成功后的跳转例如等待用户头像或登出按钮出现 # 假设登录成功后会出现一个class为‘user-avatar’的元素 wait.until( EC.visibility_of_element_located((By.CLASS_NAME, “user-avatar”)) ) print(“登录成功”) # 4. 可以进一步验证比如检查当前URL或页面标题 assert “dashboard” in driver.current_url print(“成功跳转到仪表盘页面。”) except Exception as e: print(f“测试过程中出现错误{e}”) # 可以在这里截图方便排查问题 driver.save_screenshot(“login_error.png”) finally: time.sleep(2) # 演示用实际可去掉 driver.quit()这个案例展示了如何结合隐式等待、显式等待以及使用assert进行简单断言。在实际项目中你可能会使用unittest或pytest这样的测试框架来组织用例和断言。5. 进阶之路构建可维护的自动化测试框架能写单个脚本只是起点。当你有几十上百个测试用例时如何组织代码使其易于阅读、维护和扩展就变得至关重要。这里介绍两个最核心的设计模式。5.1 Page Object Model (POM)页面对象模型这是Selenium自动化测试的圣经级设计模式。其核心思想是将测试代码操作逻辑和页面定位细节元素定位器分离。没有POM的代码糟糕的示例def test_login(): driver.find_element(By.ID, “user”).send_keys(“name”) driver.find_element(By.ID, “pass”).send_keys(“pw”) driver.find_element(By.ID, “loginBtn”).click() assert driver.find_element(By.CLASS_NAME, “welcome”).text “Welcome”问题如果登录页面的元素ID变了你需要在所有用到这些ID的测试用例中逐个修改。使用POM的代码创建页面对象类(login_page.py)from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC class LoginPage: # 1. 定义页面元素定位器集中管理 USERNAME_INPUT (By.ID, “user”) PASSWORD_INPUT (By.ID, “pass”) LOGIN_BUTTON (By.ID, “loginBtn”) WELCOME_MSG (By.CLASS_NAME, “welcome”) def __init__(self, driver): self.driver driver self.wait WebDriverWait(driver, 10) # 2. 定义页面操作方法 def enter_username(self, username): element self.wait.until(EC.visibility_of_element_located(self.USERNAME_INPUT)) element.clear() element.send_keys(username) return self # 支持链式调用 def enter_password(self, password): self.driver.find_element(*self.PASSWORD_INPUT).send_keys(password) return self def click_login(self): self.driver.find_element(*self.LOGIN_BUTTON).click() # 通常点击登录后会跳转到新页面这里返回新页面的对象 from dashboard_page import DashboardPage # 避免循环导入 return DashboardPage(self.driver) def get_welcome_message(self): return self.wait.until(EC.visibility_of_element_located(self.WELCOME_MSG)).text创建测试用例(test_login.py)import pytest from login_page import LoginPage class TestLogin: def test_valid_login(self, driver): # 假设driver通过fixture提供 login_page LoginPage(driver) dashboard_page (login_page .enter_username(“test_user”) .enter_password(“password”) .click_login()) # 断言在DashboardPage类里或这里做 assert dashboard_page.is_displayed() def test_invalid_login(self, driver): login_page LoginPage(driver) login_page.enter_username(“wrong”).enter_password(“wrong”).click_login() # 验证错误提示 assert “Invalid” in login_page.get_error_message()POM带来的好处高可维护性页面元素定位器只在一个地方Page类定义。UI一变只需修改Page类。高可读性测试用例读起来像自然语言业务逻辑清晰。低冗余页面操作被封装成方法可以在多个测试用例中复用。团队协作测试开发人员负责维护Page对象手工测试人员或业务分析师可以更容易地参与编写或阅读测试用例。5.2 数据驱动测试将测试数据如用户名、密码从测试脚本中分离出来用外部文件如JSON, CSV, Excel, YAML或数据库来管理。这样同一套测试逻辑可以用多组数据来运行。使用pytest的pytest.mark.parametrize装饰器可以轻松实现import pytest from login_page import LoginPage # 测试数据列表每个元组是一组测试数据 test_data [ (“admin”, “admin123”, True, “登录成功”), (“admin”, “wrong”, False, “密码错误”), (“”, “admin123”, False, “用户名为空”), (“admin”, “”, False, “密码为空”), ] pytest.mark.parametrize(“username, password, expected_success, description”, test_data) def test_login_with_data(username, password, expected_success, description, driver): login_page LoginPage(driver) login_page.enter_username(username).enter_password(password).click_login() if expected_success: # 验证登录成功 assert driver.current_url “/dashboard” else: # 验证登录失败并检查错误提示 error_msg login_page.get_error_message() assert error_msg is not None print(f“测试用例‘{description}’通过错误信息{error_msg}”)这样你只需要维护test_data这个列表就能轻松扩展测试场景。数据量大的时候可以从CSV或Excel文件读取。6. 避坑指南与性能优化实战在实际项目中踩过坑才能写出健壮的脚本。这里分享一些血泪教训和优化技巧。6.1 常见问题与排查技巧速查表问题现象可能原因排查与解决思路NoSuchElementException(找不到元素)1. 元素定位器写错了。2. 页面还没加载完就去查找。3. 元素在iframe/frame里。4. 元素是动态生成的Ajax。1. 用开发者工具确认定位器是否正确。2.添加显式等待等待元素出现/可见。3. 使用driver.switch_to.frame(frame_reference)切换到对应frame后再操作。4. 使用更稳定的定位方式如等具有唯一性的父元素出现或使用显式等待。ElementNotInteractableException(元素不可交互)1. 元素被遮挡如弹窗、另一个div。2. 元素不可见display: none或visibility: hidden。3. 元素未处于可操作状态如disabled。1. 检查页面是否有遮挡物可能需要先关闭弹窗。2. 等待元素变为可见 (EC.visibility_of)。3. 检查元素属性或等待其变为可点击 (EC.element_to_be_clickable)。StaleElementReferenceException(元素过期)你之前找到的元素其对应的DOM节点因为页面刷新、Ajax更新等被销毁重建了但你还在用旧的引用去操作它。重新查找元素。这是最常见的解决方式。在Page Object的方法内部每次操作前重新查找可以避免此问题。或者将查找和操作放在一个短周期内完成。脚本运行慢1. 使用了大量time.sleep。2. 隐式等待时间设置过长。3. 定位器效率低如复杂的XPath。4. 每次操作都打开/关闭浏览器。1. 用显式等待替代固定等待。2. 合理设置隐式等待时间如2-5秒。3. 优化定位器优先用ID、CSS Selector。4. 使用测试框架的setUp/tearDown或fixture让一个浏览器会话执行多个测试。Chrome CPU/内存飙升1. 浏览器版本和驱动版本不匹配。2. 打开了太多标签页或窗口未关闭。3. 脚本存在内存泄漏如大量创建未释放的对象。1. 确保chromedriver和Chrome版本匹配。2. 每个测试结束后清理driver.quit()。3. 使用driver.close()关闭非主窗口。考虑使用无头模式(ChromeOptions().add_argument(‘--headless’))减少资源占用。无法输入中文某些输入框可能有限制或事件监听。1. 确保焦点在输入框上 (element.click())。2. 尝试用ActionChains发送键 (ActionChains(driver).send_keys_to_element(element, ‘中文’).perform())。3. 极端情况下用JavaScript直接设置值driver.execute_script(“arguments[0].value‘中文’;”, element)。6.2 性能与稳定性优化技巧使用无头模式 (Headless Mode)在CI/CD服务器或不需要观察UI的测试中使用无头模式可以节省大量资源运行更快。from selenium.webdriver.chrome.options import Options chrome_options Options() chrome_options.add_argument(“--headless”) # 启用无头模式 chrome_options.add_argument(“--disable-gpu”) # 某些系统需要 chrome_options.add_argument(“--window-size1920,1080”) # 设置窗口大小 driver webdriver.Chrome(optionschrome_options)复用浏览器会话对于一组相关的测试用例不要每个用例都启动关闭浏览器。使用pytest的scope“session”的fixture让一个浏览器实例跑完所有用例能极大提升速度。import pytest pytest.fixture(scope“session”) def driver(): drv webdriver.Chrome() yield drv drv.quit()智能等待与超时设置为不同的操作设置不同的超时时间。对于很快的操作可以设短点如2秒对于加载慢的页面可以设长点如30秒。WebDriverWait的第三个参数可以设置轮询频率poll_frequency默认0.5秒在特定场景可以调整。失败截图与日志测试失败时自动截图和记录日志是定位问题的救命稻草。集成到你的测试框架中。def test_example(driver): try: # ... 测试步骤 ... assert something except AssertionError as e: # 失败时截图文件名包含时间戳和用例名 timestamp time.strftime(“%Y%m%d_%H%M%S”) driver.save_screenshot(f“screenshots/failure_{timestamp}.png”) # 记录日志 logging.error(f“Test failed: {e}”) raise # 重新抛出异常让测试框架标记为失败处理弹窗和警报 (Alert)使用driver.switch_to.alert来接受、拒绝或获取弹窗文本。# 等待alert出现并接受 WebDriverWait(driver, 5).until(EC.alert_is_present()) alert driver.switch_to.alert print(alert.text) # 获取警告文本 alert.accept() # 点击“确定” # alert.dismiss() # 点击“取消”掌握了这些核心概念、设计模式和避坑技巧你已经从一个Selenium的“门外汉”变成了一个“入门者”并且具备了向中级进阶的坚实基础。记住自动化测试不是一蹴而就的从一个小脚本开始逐步扩展到Page Object再到集成测试框架和CI/CD每一步都稳扎稳打你的测试效率和代码质量自然会不断提升。