PyCharm集成Selenium进行Web UI自动化测试实例
本文详细介绍如何在PyCharm中集成最新版Selenium 4进行Web UI自动化测试,涵盖虚拟环境配置、驱动管理机制、可执行测试脚本编写、显式等待设计及断点调试排错。
适用场景:基于 Python 与 PyCharm 进行 Web 界面自动化测试脚本开发、用例调试与质量回归验证
一、运行环境准备与 PyCharm 项目配置
搭建自动化测试工程的首要原则是保证项目依赖隔离。混用操作系统的全局 Python 环境容易因第三方包版本冲突导致脚本在不同机器上无法运行。PyCharm 原生支持对 Virtualenv 的开箱即用管理。
1.1 创建隔离的 Python 虚拟环境
打开 PyCharm,依次执行以下步骤:
- 点击顶部菜单栏 File -> New Project...。
- 在新建项目弹窗中,左侧项目类型选择 Pure Python。
- 在 Location 栏指定本地代码存放目录(例如
selenium_demo_project)。 - 在 Python Interpreter: New Virtualenv environment 中:
- Environment type:选择
Virtualenv; - Location:保持默认的子目录
venv; - Base interpreter:选择系统已安装的 Python 解释器(建议 Python 3.8 及以上版本)。
- Environment type:选择
- 点击右下角 Create 按钮完成工程初始化。PyCharm 会自动为您激活虚拟环境并建立项目结构索引。
1.2 在虚拟环境中安装 Selenium 依赖
项目建立后,我们需要在虚拟环境中安装 Selenium 库。PyCharm 提供了两种便捷方式:
- 方式一(内置终端命令行,推荐):点击 PyCharm 底部工具栏的 Terminal(终端已自动加载当前虚拟环境,提示符前缀带有
(venv)),输入以下命令并回车:
若需加速下载,可追加国内主流镜像源:pip install seleniumpip install selenium -i https://pypi.tuna.tsinghua.edu.cn/simple - 方式二(图形界面配置):打开 Settings (Preferences) -> Project: selenium_demo_project -> Python Interpreter,点击软件包列表上方的 + 号,在搜索框中检索
selenium,选中后点击 Install Package。
1.3 理解现代 Selenium 4 的驱动纳管机制变革
在早期的 Selenium 3 时代,运行 Chrome 测试必须手动下载与本地浏览器大版本严格一致的 chromedriver.exe,并将其加入系统 PATH 环境变量。一旦本地 Chrome 自动静默更新,测试脚本便会因驱动版本不匹配而崩溃抛错。
从 Selenium 4.6.0 开始,官方引入了内置的 Selenium Manager。当执行 webdriver.Chrome() 时,底层会自动检测当前操作系统已安装的 Chrome 实际版本,并在本地缓存中自动下载并匹配相应的驱动二进制程序,无需开发者手动干预。
二、编写完整的端到端自动化测试实例
接下来我们在项目根目录下新建一个 Python 文件,命名为 test_web_search.py。本实例以一个标准的网页检索与结果校验场景为例,包含浏览器初始化、防自动化识别配置、显式等待、输入交互、结果断言以及异常安全兜底。
2.1 完整测试代码
import sys
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
def create_chrome_driver():
"""配置并初始化 Chrome WebDriver 实例"""
chrome_options = Options()
# 窗口最大化以保证页面元素完整渲染并处于可点击区域
chrome_options.add_argument("--start-maximized")
# 关闭自动化测试受控提示栏与特征标记
chrome_options.add_experimental_option(
"excludeSwitches", ["enable-automation"]
)
chrome_options.add_experimental_option("useAutomationExtension", False)
# 若在无显示器的 CI/Linux 服务器执行,可取消下行注释启用无头模式
# chrome_options.add_argument("--headless=new")
# Selenium 4.6+ 会通过 Selenium Manager 自动寻找驱动,直接实例化即可
driver = webdriver.Chrome(options=chrome_options)
return driver
def test_search_workflow():
"""执行端到端检索与结果断言自动化测试流程"""
driver = create_chrome_driver()
# 声明显式等待器:超时时间设为 10 秒,轮询间隔默认 0.5 秒
wait = WebDriverWait(driver, timeout=10)
try:
print("[*] 步骤 1:打开目标测试网站...")
target_url = "https://httpbin.org/forms/post"
driver.get(target_url)
print("[*] 步骤 2:显式等待输入控件就绪并录入数据...")
# 等待客户姓名字段可见并输入
custname_input = wait.until(
EC.visibility_of_element_located((By.NAME, "custname"))
)
custname_input.clear()
custname_input.send_keys("PyCharm-Tester")
# 等待披萨尺寸单选按钮变为可点击状态并选中
medium_radio = wait.until(
EC.element_to_be_clickable(
(By.CSS_SELECTOR, "input[type='radio'][value='medium']")
)
)
medium_radio.click()
# 勾选配料多选框
topping_checkbox = wait.until(
EC.element_to_be_clickable(
(By.CSS_SELECTOR, "input[type='checkbox'][value='bacon']")
)
)
if not topping_checkbox.is_selected():
topping_checkbox.click()
print("[*] 步骤 3:提交表单并等待响应...")
submit_btn = wait.until(
EC.element_to_be_clickable((By.CSS_SELECTOR, "button"))
)
submit_btn.click()
print("[*] 步骤 4:验证表单提交响应结果...")
# 等待响应页面中渲染出的 pre 标签(包含服务器回传的 JSON 结果)
result_pre = wait.until(
EC.presence_of_element_located((By.TAG_NAME, "pre"))
)
response_text = result_pre.text
# 断言校验关键参数是否被服务器正确接收
assert "PyCharm-Tester" in response_text, "断言失败:响应内容未包含输入用户名!"
assert "medium" in response_text, "断言失败:单选框值未成功提交!"
assert "bacon" in response_text, "断言失败:复选框值未成功提交!"
print("[+] 测试执行通过:所有断言均校验成功!")
except Exception as err:
print(f"[-] 测试执行异常:{err}", file=sys.stderr)
# 出现异常时保存当前屏幕截图,辅助排查失败瞬间现场
driver.save_screenshot("test_failure_screenshot.png")
raise
finally:
print("[*] 步骤 5:释放驱动资源并彻底退出浏览器进程...")
# 无论测试用例断言成功还是抛出异常,必须调用 quit() 清理进程
driver.quit()
if __name__ == "__main__":
test_search_workflow()
2.2 运行输出示例
在 PyCharm 中右键点击该代码编辑区,选择 Run 'test_web_search',下方控制台将打印如下示例执行日志:
[*] 步骤 1:打开目标测试网站...
[*] 步骤 2:显式等待输入控件就绪并录入数据...
[*] 步骤 3:提交表单并等待响应...
[*] 步骤 4:验证表单提交响应结果...
[+] 测试执行通过:所有断言均校验成功!
[*] 步骤 5:释放驱动资源并彻底退出浏览器进程...
Process finished with exit code 0
三、核心难点攻克:元素定位策略与显式等待设计
在 UI 自动化开发过程中,超过 80% 的脚本不稳定或偶发报错是由定位表达式不合理或等待时机不恰当引起的。理解浏览器的异步渲染机制并采用正规的等待设计至关重要。
3.1 元素定位优先策略
Selenium 提供了多种定位器(By 对象)。在实际工程中,建议按以下优先级进行选型:
| 定位方式 | 调用示例 | 稳定性与性能 | 适用场景与避坑说明 |
|---|---|---|---|
| By.ID | By.ID, "username" |
最高 / 极快 | 首选方案。前提是前端开发为关键控件赋予了全局唯一 ID,且非动态随机生成。 |
| By.CSS_SELECTOR | By.CSS_SELECTOR, "form.login input[name='pw']" |
高 / 极快 | 通用首选。语法精炼,浏览器原生解析器性能高,支持组合属性、伪类与子代层级。 |
| By.NAME | By.NAME, "custname" |
中高 / 快 | 常见于表单输入控件,需确保整个表单内该 name 属性唯一。 |
| By.XPATH(相对路径) | By.XPATH, "//div[@class='card']//button[text()='提交']" |
中 / 稍慢 | 当需要根据文本内容查找、或者反向遍历父节点/兄弟节点时使用。 |
| By.XPATH(绝对路径) | By.XPATH, "/html/body/div[2]/form/div[1]/input" |
极低 / 极脆 | 严禁使用。只要前端页面稍有结构微调(例如外层包裹了一个容器 div),整个路径立即失效。 |
3.2 为什么必须弃用 time.sleep()?
许多初学者遇到元素未加载报错时,习惯随手加入 time.sleep(3)。这种做法在正规测试工程中被视为严重反模式:
- 时间冗余严重:如果一个测试用例包含 20 个交互动作,每次都盲目休眠 2 秒,整个用例至少被拖慢 40 秒。如果测试套件包含上百个用例,执行时间将被拉长数小时。
- 脆弱无保障:当网络遇到抖动或服务器压力增加导致页面加载耗时 3.1 秒时,固定休眠 3 秒的脚本仍会抛出找不到元素而崩溃。
3.3 显式等待(WebDriverWait)常用预期条件
显式等待通过 WebDriverWait(driver, timeout).until(condition) 实现:它会在预设时间内,按照固定的轮询频率(默认 500ms)不断检查条件是否达成,一旦达成立即放行,绝不多等 1 毫秒。
EC.visibility_of_element_located((By, value)):等待元素已挂载到 DOM 树且在页面上可见(宽高大于 0 且无 display:none)。EC.element_to_be_clickable((By, value)):等待元素既可见又处于非禁用状态(可被点击),用于按钮、链接与选择框。EC.presence_of_element_located((By, value)):仅检测 DOM 树是否存在此节点,不要求界面可见(常用于检测后台异步返回的隐藏字段或 pre 数据标签)。EC.text_to_be_present_in_element((By, value), "成功"):等待指定元素的内部文本出现期望的内容,适合动态异步回显验证。
四、在 PyCharm 中进行测试运行与高效断点调试
自动化测试脚本编写过程中,最耗费时间的往往是“元素找不着”或“点击无反应”时的反复调试。熟练运用 PyCharm 的调试工具能成倍缩短排查耗时。
4.1 配置 Run/Debug Configurations
在 PyCharm 右上角运行配置区域,点击下拉框选择 Edit Configurations...:
- 确认 Python Interpreter 指向当前工程的
venv/bin/python(或 Windows 下的venv\Scripts\python.exe)。 - Working directory 默认为工程根路径。如果测试代码需要读取同目录下的测试数据文件(如 JSON/Excel),确保该工作路径准确无误。
4.2 设置断点与启动 Debug 模式
在代码编辑行号右侧单击即可打上红色圆点断点(例如打在 submit_btn.click() 前)。右键点击代码选择 Debug 'test_web_search':
- 程序运行到断点处会自动挂起,此时浏览器窗口会停留在当前操作状态,页面不会关闭。
- PyCharm 底部自动弹出 Debug 窗口,在 Variables 窗格中可以直接查看当前时刻
driver.current_url、driver.title以及定位到的 WebElement 属性。
4.3 终极利器:利用 Debugger Console 实时测试定位表达式
>>>)。
在此控制台中,您可以直接输入 Python 代码与当前处于暂停状态的浏览器进行实时通讯,例如:
# 实时测试选择器是否能精确定位到唯一目标
>>> driver.find_elements(By.CSS_SELECTOR, "button.submit-btn")
[<selenium.webdriver.remote.webelement.WebElement (session="...", element="...")>]
# 实时打印该元素当前的可见文本与属性值
>>> driver.find_element(By.CSS_SELECTOR, "button.submit-btn").text
'立即提交'
通过实时命令行验证无误后,再将最终确定的选择器复制回脚本源码中。这样完全不需要每次修改代码后都重启浏览器跑完整流程,极大提升编写与定位效率。
五、常见问题排查与工程化避坑指南
在团队协作或持续集成落地过程中,通常会遇到以下几类典型报错与隐患:
5.1 报错:SessionNotCreatedException
表现:执行脚本时直接崩溃,提示“This version of ChromeDriver only supports Chrome version XX”或无法启动会话。
排查与解决:
- 检查本地系统 Chrome 是否刚被静默升级,导致缓存的驱动过旧;
- 运行
pip install --upgrade selenium将 Selenium 升级到最新版本,确保内置的 Selenium Manager 包含最新的浏览器映射规则; - 清理系统临时目录下的缓存驱动(Windows 位于
%USERPROFILE%/.cache/selenium,Mac/Linux 位于~/.cache/selenium),重启脚本即可自动重新拉取对应驱动。
5.2 报错:TimeoutException
表现:显式等待超时(达到设定的 10 秒后崩溃)。
排查与解决:
- 元素是否位于 iframe 内部:Selenium 默认只能检索顶层 DOM。若目标元素嵌套在
<iframe>中,必须先执行driver.switch_to.frame("iframe_id_or_element")切入内联子框架,操作完毕后再通过driver.switch_to.default_content()切回主文档。 - 页面是否打开了新浏览器标签页:如果点击某个链接后浏览器弹出了新窗口,需要先切换窗口句柄:
driver.switch_to.window(driver.window_handles[-1]) - 元素被浮动弹窗或遮罩层遮挡:常见报错为
ElementClickInterceptedException。可使用显式等待EC.invisibility_of_element_located((By.CLASS_NAME, "loading-mask"))等待遮罩层消失,或借助 JavaScript 脚本直接触发点击:driver.execute_script("arguments[0].click();", element)。
5.3 警惕:后台僵尸进程与 driver.close() 误区
driver.close() 仅关闭当前焦点的标签页窗口,若后台还有其他窗口或进程,ChromeDriver 服务依然常驻内存;而 driver.quit() 会向驱动发送退出指令,完整杀灭整个浏览器会话与本地驱动进程。
因此,所有与浏览器交互的代码必须严格包裹在 try...finally 结构中,并在 finally 块中调用 driver.quit()。否则一旦测试中间抛出异常导致脚本提前中断,后台将残留大量游离的 Chrome 进程,迅速耗尽系统内存。
六、总结
PyCharm 与 Selenium 4 的结合为 Web UI 自动化测试提供了高效而稳定的技术底座。通过 PyCharm 的虚拟环境管理,我们避免了繁杂的全局依赖污染;借助 Selenium 4 内置的 Selenium Manager,彻底摆脱了手动维护驱动版本与环境变量的旧式负担;而在代码层面,坚持使用以 ID 和语义化 CSS 为核心的定位策略,并全面采用显式等待机制替代盲目的线程休眠,是保障用例健壮、抗网络延迟波动的核心保障。
在掌握单用例的编写与断点调试后,后续可以进一步结合 pytest 单元测试框架实现多用例批量执行、参数化驱动测试数据以及生成 Allure 自动化测试可视化报告,将自动化测试平滑接入团队的 CI/CD 交付流水线中。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













