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

Selenium与ChromeDriver环境搭建及自动化测试入门实战

1. 项目概述:为什么我们需要浏览器自动化?

在软件开发和测试的日常工作中,我们经常需要重复执行一些基于网页的操作,比如数据抓取、表单提交、功能回归测试,或者验证某个网页在不同条件下的表现。手动点击、输入、刷新,不仅效率低下,而且容易出错,尤其是在需要覆盖大量测试用例或执行高频次任务时。这时,浏览器自动化技术就成了我们的得力助手。

Selenium 正是这个领域的“瑞士军刀”。它是一个强大的开源工具集,支持多种编程语言(如 Python、Java、C#)和浏览器(如 Chrome、Firefox),允许我们编写脚本程序来模拟真实用户的操作。而 ChromeDriver 则是连接 Selenium 脚本与谷歌 Chrome 浏览器的“桥梁”或“翻译官”。没有它,你的 Selenium 指令就无法传达给 Chrome 浏览器。

本指南旨在提供一个从零开始、手把手式的完整流程,帮助你搭建起 Selenium 与 ChromeDriver 的环境,并编写出第一个可运行的自动化测试脚本。无论你是测试工程师、开发人员,还是对自动化感兴趣的数据分析师,都能从中找到清晰的路径。我们将避开那些官方文档里语焉不详的坑,直接分享一线实战中最有效的配置方法和编码技巧。

2. 环境准备与核心组件安装

自动化测试的基石是一个稳定、匹配的环境。任何版本的不匹配都可能导致脚本运行失败,因此这一步至关重要。

2.1 谷歌浏览器(Chrome)的安装与版本确认

首先,你需要一台安装了谷歌浏览器的机器。虽然听起来简单,但版本是关键。

安装与检查:

  1. 访问谷歌浏览器官网或通过可靠的软件管理工具安装最新稳定版的 Chrome。
  2. 安装后,在浏览器地址栏输入chrome://version/并回车。这个页面会显示你的 Chrome 的完整版本号,例如128.0.6613.138。请务必记下这个版本号,尤其是主版本号(如128),它是我们选择 ChromeDriver 的依据。

注意:很多自动化失败都源于浏览器与驱动版本不匹配。请确保你知晓自己 Chrome 的确切版本。

2.2 ChromeDriver 的下载与配置

ChromeDriver 是一个独立的可执行文件,它实现了 WebDriver 协议。Selenium 通过这个协议向 ChromeDriver 发送指令,后者再控制 Chrome 浏览器。

下载步骤:

  1. 访问 ChromeDriver 的官方下载站点(通常由 Chromium 项目维护)。你需要找到一个能提供历史版本下载的镜像站,因为你的 Chrome 版本可能不是最新的。
  2. 在下载页面,根据你记下的 Chrome主版本号(如 128),找到对应的 ChromeDriver 版本。通常版本号会完全匹配或非常接近。
  3. 选择与你的操作系统(Windows、macOS、Linux)对应的压缩包进行下载。

配置步骤(以 Windows 为例):

  1. 将下载的chromedriver.exe文件解压出来。
  2. 为了全局可用,建议将其放置在一个固定的目录,例如C:\WebDriver\,并将此目录的路径添加到系统的PATH环境变量中。
  3. 验证配置:打开命令提示符(CMD)或 PowerShell,输入chromedriver --version并回车。如果正确显示了版本信息,说明配置成功。

对于 macOS/Linux 用户:

  • 将解压后的chromedriver文件移动到/usr/local/bin/目录(可能需要sudo权限),这样它就可以在终端中直接调用了。
  • 同样,可以通过chromedriver --version命令验证。

2.3 Selenium 库的安装

Selenium 提供了编程语言绑定的库。这里我们以最流行的 Python 为例。

通过 Python 的包管理工具 pip 可以轻松安装:

pip install selenium

如果你使用的是 Python 3,可能需要使用pip3

pip3 install selenium

为了确保环境的纯净和依赖管理,强烈建议在虚拟环境(如venvconda)中进行安装和后续开发。

至此,三大核心组件:浏览器(Chrome)、驱动(ChromeDriver)、控制库(Selenium)均已就位。它们之间的关系可以简单理解为:你的 Python 脚本(使用 Selenium 库) -> ChromeDriver -> Chrome 浏览器。

3. 第一个自动化脚本:从启动浏览器到简单操作

理论说再多不如动手一试。让我们编写一个最简单的脚本,感受一下自动化的魅力。

3.1 基础脚本结构

创建一个新的 Python 文件,例如first_test.py,并输入以下代码:

from selenium import webdriver from selenium.webdriver.common.by import By import time # 1. 创建 Chrome 浏览器驱动选项(可选,用于配置浏览器行为) options = webdriver.ChromeOptions() # 例如,以无头模式运行(不显示浏览器界面),适合在服务器上执行 # options.add_argument('--headless') # 禁用GPU加速,有时可避免一些渲染问题 # options.add_argument('--disable-gpu') # 2. 初始化 WebDriver,传入选项 driver = webdriver.Chrome(options=options) try: # 3. 导航到一个网页 driver.get("https://www.baidu.com") print(f"已打开页面,标题是:{driver.title}") # 4. 进行一些简单的操作 # 通过元素的ID定位搜索框,并输入文本 search_box = driver.find_element(By.ID, "kw") search_box.send_keys("Selenium 自动化测试") # 定位搜索按钮并点击 search_button = driver.find_element(By.ID, "su") search_button.click() # 等待一下,让页面加载结果 time.sleep(2) # 5. 验证结果(简单示例:打印当前页面标题) print(f"搜索后页面标题是:{driver.title}") finally: # 6. 等待几秒后关闭浏览器 time.sleep(5) driver.quit()

代码逐行解析:

  • from selenium import webdriver:导入 Selenium 的核心 WebDriver 模块。
  • from selenium.webdriver.common.by import By:导入By类,它提供了定位页面元素的各种策略(如ID、NAME、CSS_SELECTOR等)。这是 Selenium 4 的推荐写法,更清晰。
  • webdriver.Chrome(options=options):这行代码是关键。它会启动 ChromeDriver 进程,并由 ChromeDriver 打开一个新的 Chrome 浏览器实例。options参数允许我们定制浏览器启动时的状态。
  • driver.get(url):命令浏览器导航到指定的 URL。
  • driver.find_element(By.ID, "kw"):在页面中查找一个 ID 属性为 “kw” 的 HTML 元素。这是百度搜索框的ID。
  • element.send_keys(“text”):模拟键盘输入,向找到的元素(搜索框)输入文本。
  • element.click():模拟鼠标点击操作。
  • driver.quit():非常重要!它会关闭所有关联的浏览器窗口,并终止 ChromeDriver 进程。使用try...finally结构能确保即使脚本中途出错,浏览器也会被正确关闭,避免残留进程占用资源。

运行这个脚本,你会看到一个 Chrome 浏览器自动打开,访问百度,输入关键词并点击搜索,然后停留片刻后关闭。控制台会打印出页面标题的变化。

3.2 元素定位:自动化操作的“眼睛”

自动化测试的核心是与页面上的元素(按钮、输入框、链接等)进行交互。而交互的前提是“找到”它们。Selenium 提供了多种定位策略:

定位方式 (By.)描述示例适用场景
ID通过元素的id属性定位By.ID, “username”首选。ID通常唯一,定位最快最准。
NAME通过元素的name属性定位By.NAME, “password”常用于表单元素。
CLASS_NAME通过元素的class属性定位By.CLASS_NAME, “btn-primary”当多个元素共享同一类名时,可能返回多个元素。
TAG_NAME通过HTML标签名定位By.TAG_NAME, “input”通常用于查找某一类标签,如所有输入框。
LINK_TEXT通过超链接的完整文本定位By.LINK_TEXT, “忘记密码?”精准定位文字链接。
PARTIAL_LINK_TEXT通过超链接的部分文本定位By.PARTIAL_LINK_TEXT, “忘记”文本链接的部分匹配。
CSS_SELECTOR通过CSS选择器定位By.CSS_SELECTOR, “#container .list li:nth-child(2)”功能强大且灵活,语法与前端CSS一致,推荐掌握。
XPATH通过XML路径语言定位By.XPATH, “//div[@id=‘login’]/form/input[1]”功能最强大,可以遍历整个DOM树,但速度可能稍慢,语法相对复杂。

实操心得:

  • 优先级ID>NAME>CSS_SELECTOR>XPATH> 其他。尽量使用简单的、唯一的属性定位。
  • 如何获取元素属性:在 Chrome 浏览器中,按 F12 打开开发者工具,使用左上角的箭头工具点击页面元素,即可在 “Elements” 面板中查看其idclassname等属性。右键元素还可以直接 “Copy” -> “Copy selector” (CSS选择器) 或 “Copy XPath”,非常方便。
  • find_elementfind_elements:前者返回第一个匹配的元素(一个WebElement对象),后者返回所有匹配元素的列表。如果找不到元素,find_element会抛出NoSuchElementException

4. 核心操作与高级等待策略

仅仅打开页面和点击是不够的。真实的自动化场景需要处理页面加载、元素状态变化、弹窗等复杂情况。

4.1 常见的浏览器操作

除了get()click()send_keys(),以下操作也非常常用:

  • 导航
    driver.back() # 后退 driver.forward() # 前进 driver.refresh() # 刷新
  • 窗口和标签页
    driver.maximize_window() # 最大化窗口 driver.get_window_size() # 获取窗口尺寸 driver.set_window_size(1024, 768) # 设置窗口尺寸 original_window = driver.current_window_handle # 获取当前窗口句柄 driver.switch_to.new_window(‘tab’) # 打开新标签页 for handle in driver.window_handles: # 遍历所有窗口句柄 if handle != original_window: driver.switch_to.window(handle) # 切换到新窗口 break
  • 执行JavaScript:对于某些 Selenium 原生API难以实现的操作,可以直接注入JS。
    # 滚动到页面底部 driver.execute_script(“window.scrollTo(0, document.body.scrollHeight);”) # 修改元素属性 driver.execute_script(“arguments[0].setAttribute(‘style’, ‘color: red’);”, element)
  • 处理弹窗/Alert
    alert = driver.switch_to.alert # 切换到alert print(alert.text) # 获取提示文本 alert.accept() # 点击“确定” # alert.dismiss() # 点击“取消”

4.2 等待机制:自动化稳定的关键

页面元素加载需要时间,直接操作可能导致NoSuchElementException。使用time.sleep()是一种简单粗暴的固定等待,但效率低下且不可靠(网络或性能波动会导致等待时间不足或过长)。Selenium 提供了两种智能的等待方式:

1. 隐式等待 (Implicit Wait)在 WebDriver 对象的整个生命周期内设置一个全局的等待时间。当查找元素时,如果元素没有立即出现,WebDriver 会轮询DOM(默认每0.5秒)直到找到该元素或超时。

driver.implicitly_wait(10) # 单位:秒

注意:隐式等待只需设置一次。它只对find_elementfind_elements方法生效。对于页面跳转等操作无效。

2. 显式等待 (Explicit Wait)针对某个特定条件进行等待,更加灵活和精确。你需要定义“等待条件”和“最长等待时间”。

from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # 等待最多10秒,直到ID为‘result’的元素出现在DOM中并且可见 wait = WebDriverWait(driver, 10) element = wait.until(EC.presence_of_element_located((By.ID, “result”))) # 或者等待元素可点击 button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, “.submit-btn”))) button.click()

expected_conditions模块提供了很多预定义条件,如:

  • visibility_of_element_located: 元素可见(不仅存在,而且宽高大于0)。
  • element_to_be_clickable: 元素可见且可点击。
  • title_contains: 页面标题包含特定文字。
  • alert_is_present: 出现Alert弹窗。

最佳实践:

  • 混合使用:通常设置一个较短的隐式等待(如5秒)作为全局后备,然后在关键操作(如点击后等待新页面元素出现)处使用更精确的显式等待。
  • 避免混用:隐式等待和显式等待一起使用时,最长等待时间可能会叠加,导致等待时间远超预期。建议以显式等待为主,谨慎设置隐式等待时间。
  • 抛弃time.sleep:在正式的自动化脚本中,应尽量避免使用固定的time.sleep,改用显式等待来提升脚本的稳定性和执行速度。

5. 实战进阶:框架搭建与常见问题排查

当脚本越来越多,我们就需要考虑如何组织代码,使其更易于维护、扩展和复用。同时,也会遇到各种棘手的运行时问题。

5.1 简单的 Page Object Model (POM) 模式

POM 是一种设计模式,将每个网页或页面组件封装成一个类,页面的元素定位和操作都在这个类中完成。测试脚本则通过调用这些页面对象的方法来进行操作。这样做的好处是:

  • 代码复用:元素定位逻辑集中在一处,修改时只需改一个地方。
  • 可读性强:测试脚本读起来像自然语言,login_page.enter_username(“admin”)
  • 易于维护:页面结构变化时,只需修改对应的页面对象类。

一个简单的例子:

# base_page.py - 基础页面类,封装通用操作 from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC class BasePage: def __init__(self, driver): self.driver = driver self.wait = WebDriverWait(driver, 10) def find(self, by, locator): return self.wait.until(EC.presence_of_element_located((by, locator))) def click(self, by, locator): element = self.wait.until(EC.element_to_be_clickable((by, locator))) element.click() # login_page.py - 登录页面对象 from selenium.webdriver.common.by import By from base_page import BasePage class LoginPage(BasePage): # 定位器 USERNAME_INPUT = (By.ID, “username”) PASSWORD_INPUT = (By.ID, “password”) LOGIN_BUTTON = (By.CSS_SELECTOR, “button[type=‘submit’]”) ERROR_MSG = (By.CLASS_NAME, “error-message”) def enter_username(self, username): self.find(*self.USERNAME_INPUT).send_keys(username) def enter_password(self, password): self.find(*self.PASSWORD_INPUT).send_keys(password) def click_login(self): self.click(*self.LOGIN_BUTTON) def get_error_message(self): return self.find(*self.ERROR_MSG).text # test_login.py - 测试脚本 from selenium import webdriver from login_page import LoginPage def test_valid_login(): driver = webdriver.Chrome() driver.get(“https://example.com/login”) login_page = LoginPage(driver) login_page.enter_username(“testuser”) login_page.enter_password(“securepass”) login_page.click_login() # 断言登录成功,例如检查是否跳转到首页 assert “Dashboard” in driver.title driver.quit()

这只是 POM 的雏形。在实际项目中,你还可以结合unittestpytest等测试框架,并加入数据驱动、日志记录、截图等功能,构建完整的自动化测试框架。

5.2 常见问题与排查技巧实录

即使环境配置正确,脚本逻辑无误,在实际运行中仍会遇到各种问题。以下是一些常见“坑”及其解决方法:

问题1:SessionNotCreatedException: Message: session not created: This version of ChromeDriver only supports Chrome version XX

  • 原因:ChromeDriver 版本与 Chrome 浏览器版本不匹配。
  • 解决:严格按照本文 2.1 和 2.2 的步骤,核对并下载对应版本的 ChromeDriver。可以尝试使用webdriver-manager这个第三方库,它能自动下载匹配的驱动。
    pip install webdriver-manager
    from selenium import webdriver from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.chrome.service import Service service = Service(ChromeDriverManager().install()) driver = webdriver.Chrome(service=service)

问题2:NoSuchElementException: Message: no such element: Unable to locate element

  • 原因:元素定位失败。这是最常见的问题。
  • 排查
    1. 检查定位器:确认By策略和定位字符串是否正确。在开发者工具中使用Ctrl+F,在搜索框内输入你的 CSS 选择器或 XPath,看是否能唯一匹配到目标元素。
    2. 检查等待时间:元素可能还没加载出来。增加隐式/显式等待时间,或使用更合适的等待条件(如visibility_of而非presence_of)。
    3. 检查iframe:如果目标元素在<iframe>内,需要先切换到对应的 iframe 才能操作。
      driver.switch_to.frame(“iframe_name_or_id”) # 通过name或id切换 # driver.switch_to.frame(driver.find_element(By.TAG_NAME, “iframe”)) # 通过元素切换 # 操作iframe内的元素... driver.switch_to.default_content() # 操作完成后切回主文档
    4. 检查页面是否跳转/刷新:操作后页面发生了变化,之前的元素引用可能已经“过时”。需要在操作后重新定位元素。

问题3:ElementClickInterceptedExceptionElementNotInteractableException

  • 原因:元素被其他元素(如弹窗、遮罩层)遮挡,或者元素本身不可交互(如disabled状态、不可见)。
  • 解决
    1. 使用element_to_be_clickable条件进行等待,确保元素可点击。
    2. 检查是否有弹窗需要先关闭。
    3. 尝试用 JavaScript 直接点击:driver.execute_script(“arguments[0].click();”, element)
    4. 滚动元素到视图中:driver.execute_script(“arguments[0].scrollIntoView(true);”, element)

问题4:脚本在无头模式 (--headless) 下运行失败,但在有界面模式下正常。

  • 原因:无头模式下的浏览器环境(如视口大小、用户代理等)与有界面模式略有不同,可能导致某些页面布局或检测逻辑发生变化。
  • 解决
    1. 为无头模式设置一个明确的窗口大小:options.add_argument(‘--window-size=1920,1080’)
    2. 设置一个常见的用户代理字符串,避免被网站识别为爬虫(谨慎使用,遵守网站规则)。
    3. 如果问题依旧,尝试在关键步骤后添加短暂的time.sleep或更长的显式等待,因为无头模式下的渲染/JS执行速度可能不同。

问题5:如何调试运行中的脚本?

  • 暂停与检查:在脚本中插入input(“按回车键继续...”),可以让脚本暂停,此时你可以手动检查浏览器页面状态。
  • 截图:在出错或关键步骤后截图,便于事后分析。
    driver.save_screenshot(“error_screenshot.png”) # 或者截取特定元素 element.screenshot(“element_screenshot.png”)
  • 打印页面源码print(driver.page_source)可以打印当前页面的 HTML,有助于分析动态加载的内容。

自动化测试不是一蹴而就的,它需要耐心地调试和不断地优化。从最简单的打开页面开始,逐步增加复杂的操作和逻辑,并善用等待机制和异常处理,你的脚本会变得越来越健壮。记住,核心思想是让你的程序像一位有耐心、不会出错的“标准用户”一样去操作浏览器。

http://www.gsyq.cn/news/1608190.html

相关文章:

  • 终极Chromium优化浏览器:Thorium让你的上网速度提升30%
  • UniExtract2:一站式文件提取解决方案,轻松应对500+种格式挑战
  • ROFL-Player技术解码:英雄联盟回放文件的多版本兼容性处理机制
  • Vue二维码组件深度解析:qrcode.vue架构设计与性能优化
  • 淘宝 拼多多订单同步 API 落地避坑(多店 ERP 通用,彻底解决漏单 / 重单 / 状态错乱)
  • 【一周安全资讯】国家网信办等三部门联合公布《网络数据安全风险评估办法》;印度塔塔电子遭勒索,苹果、特斯拉超630G数据
  • 解决Devika与Playwright异步死锁:3行代码隔离同步API冲突
  • STM32CubeIDE实战:基于USB Device的虚拟串口通信设计与优化
  • 湘美书院谈AI时代的教育箴言,天生我材必有用
  • Java for 循环
  • 面包板到PCB:快速原型验证的最佳实践 —— 模块化设计与可测试性
  • 3分钟快速安装Windows包管理器:PowerShell一键安装Winget完整教程
  • DCT域图像隐写实战:从MATLAB代码到鲁棒性调优
  • 【Unity3D】Unity 编辑器核心窗口功能详解与高效布局指南
  • 零拷贝网络:Linux splice/sendfile 系统调用的 Go 实现
  • MATLAB回调函数实战:从函数句柄到ButtonDownFcn的交互设计
  • 告别繁琐配置:PowerShell智能脚本帮你快速部署Windows包管理器
  • Windows Cleaner:专治C盘爆红与系统卡顿的终极解决方案
  • 大庆装饰公司怎么选不踩坑!本土靠谱装饰公司、全屋定制、别墅商装优选攻略
  • 2026年AI图片翻译深度实测:电商图、海报、漫画如何做到“无痕“本地化?5款工具对比
  • NXP I.MX6ULL DDR3实战:从配置脚本到压力测试的完整流程解析
  • tinyriscv学习记录之五
  • 5个技巧快速上手MediaCrawler:多平台数据采集终极指南
  • 为什么90%的R语言学习者都半途而废?
  • Pikachu靶场文件包含漏洞实战:从原理到渗透测试全解析
  • GPS/北斗模块实战入门:从选型到嵌入式系统集成
  • LeetCode刷题 day25
  • Wfuzz模糊测试工具:Web渗透测试中的瑞士军刀
  • Solidworks二次开发实战:解析选中圆形边的几何中心点
  • 2026AI在线抠图工具整理:免费无水印、商用合规专业平台实操指南