Selenium 软件测试入门保姆级(适配 Python 3.13 + Selenium 4.6+)
·
Selenium 软件测试入门保姆级
(适配 Python 3.13 + Selenium 4.6+)
一、我踩过的坑(新手必看避坑指南)
- Chrome 驱动下载失败,代码卡住不动
- 原因:国内网络无法访问谷歌官方驱动服务器,Selenium Manager 自动下载超时
- 解决:
- 临时方案:用
webdriver-manager从国内镜像下载驱动 - 永久方案:让
webdriver-manager下载一次后,驱动会被缓存,后续原生写法可直接识别
- 临时方案:用
executable_path参数报错- 原因:Selenium 4.6+ 已经废除了
executable_path参数,不再需要手动指定驱动路径 - 解决:直接使用
webdriver.Chrome(options=chrome_opt),无需写驱动路径
- 原因:Selenium 4.6+ 已经废除了
- 浏览器启动慢,要等十几秒才打开
- 原因:Selenium 启动时会尝试校验版本,国内网络导致超时等待
- 解决:添加启动参数,跳过校验、禁用多余功能
- 旧代码(4.8以下版本)会报错
- 原因:旧版依赖手动驱动路径,新版有自动驱动管理,且部分参数写法更新(如
--headless改为--headless=new) - 解决:使用适配新版的初始化代码
- 原因:旧版依赖手动驱动路径,新版有自动驱动管理,且部分参数写法更新(如
二、Selenium 环境搭建与浏览器初始化(适配我的版本)
1. 前置依赖安装
# 安装最新版 Selenium
pip install --upgrade selenium
# 可选:解决驱动下载问题的辅助工具(国内推荐)
pip install webdriver-manager
2. 浏览器初始化封装(可复用模板)
新建文件 browser_init.py,复制以下代码:
# -*- coding: utf-8 -*-
# @Description : 适配 Python 3.13 + Selenium 4.6+ 的 Chrome 浏览器初始化模块
import time
import json
import os
import shutil
from dataclasses import dataclass, asdict
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
@dataclass
class WebDriveConf:
"""浏览器全局配置实体类,统一管理所有启动参数"""
user_data_dir: str = 'D:\\webDriverTempDir' # 浏览器缓存目录
is_use_cache: int = 0 # 0=不使用缓存,1=使用缓存
is_load_page: int = 1 # 0=无界面后台运行,1=弹出窗口
is_load_img: int = 0 # 0=不加载图片(提速),1=加载图片
is_ignore_certificate: int = 1 # 1=忽略证书错误,0=校验证书
is_incognito: int = 1 # 1=无痕模式,0=普通模式
def to_dict(self):
"""配置转字典,用于写入json文件"""
return asdict(self)
def read_json_config(self, file_path: str):
"""读取配置文件,不存在则自动创建默认配置"""
if not os.path.exists(file_path):
with open(file_path, "w", encoding="utf-8") as f:
json.dump(self.to_dict(), f, indent=4, ensure_ascii=False)
with open(file_path, "r", encoding="utf-8") as f:
return json.load(f)
class ChromeWebDriver:
"""Chrome浏览器初始化封装类,后续所有自动化测试脚本都调用它"""
def __init__(self, conf: WebDriveConf):
self.conf = conf
self.chrome_opt = Options()
# --------------------------
# 核心优化参数(解决国内启动卡顿、模拟真实用户)
# --------------------------
self.chrome_opt.add_argument("--no-sandbox")
self.chrome_opt.add_argument("--disable-gpu")
self.chrome_opt.add_argument('--window-size=1366,768')
self.chrome_opt.add_argument('--ignore-certificate-errors')
self.chrome_opt.add_argument('--disable-extensions')
# 禁用弹窗 + 设置下载路径(测试常用)
self.chrome_opt.add_experimental_option('prefs', {
'profile.default_content_settings.popups': 0,
'download.default_directory': './downloads'
})
# 隐藏自动化控制提示,避免被反爬识别
self.chrome_opt.add_experimental_option('excludeSwitches', ['enable-automation'])
self.chrome_opt.add_experimental_option('useAutomationExtension', False)
# --------------------------
# 用户数据目录配置(测试用例隔离)
# --------------------------
self.chrome_opt.add_argument(f'--user-data-dir={self.conf.user_data_dir}')
if not self.conf.is_use_cache and os.path.exists(self.conf.user_data_dir):
shutil.rmtree(self.conf.user_data_dir)
if not os.path.exists(self.conf.user_data_dir):
os.makedirs(self.conf.user_data_dir)
# --------------------------
# 可选模式配置(根据测试场景选择)
# --------------------------
if not self.conf.is_load_page:
self.chrome_opt.add_argument('--headless=new') # 新版无界面写法(CI/CD 常用)
if not self.conf.is_load_img:
self.chrome_opt.add_argument('--blink-settings=imagesEnabled=false')
if self.conf.is_incognito:
self.chrome_opt.add_argument('--incognito')
# --------------------------
# 启动浏览器(新版核心:自动驱动管理)
# --------------------------
self.chromedriver = webdriver.Chrome(options=self.chrome_opt)
# 浏览器启动后配置(测试稳定性必备)
self.chromedriver.set_page_load_timeout(30) # 页面加载超时30秒
# 测试运行(验证初始化是否成功)
if __name__ == '__main__':
conf = WebDriveConf()
config_data = conf.read_json_config("web_driver_conf.json")
run_conf = WebDriveConf(**config_data)
browser = ChromeWebDriver(run_conf)
browser.chromedriver.get("https://www.baidu.com")
print("浏览器初始化成功!")
time.sleep(5)
browser.chromedriver.quit()
三、Selenium 核心学习内容(按软件测试场景排序)
阶段1:基础元素定位(测试核心)
1. 常用定位方式(适配 Selenium 4.x)
| 定位方式 | 适用场景 | 示例代码 |
|---|---|---|
By.ID |
元素有唯一ID(优先使用,稳定性最高) | driver.find_element(By.ID, "kw") |
By.NAME |
表单元素有name属性 | driver.find_element(By.NAME, "wd") |
By.XPATH |
复杂元素、无ID/NAME的场景 | driver.find_element(By.XPATH, '//input[@class="s_ipt"]') |
By.CSS_SELECTOR |
前端常用,语法简洁 | driver.find_element(By.CSS_SELECTOR, "input.s_ipt") |
2. 元素等待(测试稳定性必备,替代 time.sleep())
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# 显式等待(推荐):最多等待10秒,直到元素出现
wait = WebDriverWait(driver, 10)
search_box = wait.until(EC.presence_of_element_located((By.ID, "kw")))
阶段2:常见页面操作(测试用例高频场景)
1. 元素交互操作
# 输入文本
search_box.send_keys("软件测试学习")
# 点击按钮
search_btn = driver.find_element(By.ID, "su")
search_btn.click()
# 获取元素文本
print("搜索结果标题:", driver.find_element(By.XPATH, '//h3[1]/a').text)
# 获取元素属性
print("搜索框placeholder:", search_box.get_attribute("placeholder"))
2. 窗口与标签页操作
# 获取当前窗口句柄
current_handle = driver.current_window_handle
# 切换到新标签页
driver.switch_to.window(driver.window_handles[-1])
# 关闭当前标签页
driver.close()
# 切换回主窗口
driver.switch_to.window(current_handle)
3. 表单与弹窗处理
# 下拉框选择
from selenium.webdriver.support.ui import Select
select = Select(driver.find_element(By.ID, "city"))
select.select_by_visible_text("北京")
# 处理alert弹窗
alert = driver.switch_to.alert
alert.accept() # 点击确定
alert.dismiss() # 点击取消
alert.send_keys("输入内容") # 弹窗输入文本
阶段3:进阶测试技巧(解决复杂场景)
1. iframe 切换(页面内嵌框架)
# 切换到iframe
driver.switch_to.frame("iframe_id")
# 操作iframe内的元素
driver.find_element(By.ID, "inner-btn").click()
# 切换回主页面
driver.switch_to.default_content()
2. 鼠标键盘高级操作
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
# 鼠标悬停
ActionChains(driver).move_to_element(element).perform()
# 双击元素
ActionChains(driver).double_click(element).perform()
# 键盘快捷键(Ctrl+A全选文本)
element.send_keys(Keys.CONTROL, "a")
3. 测试用例模板(可直接复用)
from browser_init import ChromeWebDriver, WebDriveConf
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import unittest
class BaiduSearchTest(unittest.TestCase):
def setUp(self):
# 初始化浏览器
conf = WebDriveConf()
config_data = conf.read_json_config("web_driver_conf.json")
self.browser = ChromeWebDriver(WebDriveConf(**config_data))
self.driver = self.browser.chromedriver
self.wait = WebDriverWait(self.driver, 10)
def test_baidu_search(self):
# 1. 打开百度首页
self.driver.get("https://www.baidu.com")
# 2. 定位搜索框并输入内容
search_box = self.wait.until(EC.presence_of_element_located((By.ID, "kw")))
search_box.send_keys("Selenium软件测试")
# 3. 点击搜索按钮
self.wait.until(EC.element_to_be_clickable((By.ID, "su"))).click()
# 4. 验证结果(断言)
self.assertIn("Selenium软件测试", self.driver.title)
def tearDown(self):
# 关闭浏览器
self.driver.quit()
if __name__ == '__main__':
unittest.main()
四、关于 browsermob-proxy 的说明
1. 适用场景
当网页数据通过 Canvas 渲染、无法通过元素定位获取,或者需要抓取接口请求数据做接口测试时,才需要使用代理抓包。
2. 依赖与门槛
-
需要安装 Java JDK 8+
-
软件测试中,大部分场景不需要抓包,优先用元素定位+接口测试工具(如Postman)更高效
3.Selenium+browsermob-proxy获取网络请求
第一步:下载 browsermob-proxy
-
访问 GitHub 发布页:
https://github.com/lightbody/browsermob-proxy/releases -
下载最新版的
.zip文件(例如browsermob-proxy-2.1.4-bin.zip)。
第二步:安装 Python 模块
在 PyCharm 的 Terminal(或 cmd)中执行:
pip install browsermob-proxy
第三步:编写代码(适配自己的路径)
import time
from selenium import webdriver
from browsermobproxy import Server
# 1. 启动 browsermob-proxy 服务器(路径改成你自己解压的位置)
server = Server("D:\\browsermob-proxy-2.1.4\\bin\\browsermob-proxy.bat")
server.start()
proxy = server.create_proxy() # 创建一个代理,端口自动分配
# 2. 配置 Chrome 使用该代理
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument(f'--proxy-server={proxy.proxy}')
# 如果你之前有额外的配置(如无痕、不加载图片等),可以继续加上
# chrome_options.add_argument('--incognito')
# chrome_options.add_argument('--blink-settings=imagesEnabled=false')
# 3. 启动浏览器
driver = webdriver.Chrome(options=chrome_options)
# 4. 开始记录网络请求(生成一个 HAR 文件)
proxy.new_har("baidu", options={'captureHeaders': True, 'captureContent': True})
# 5. 访问目标网页
driver.get("https://www.baidu.com")
# 6. 等待页面加载
time.sleep(3)
# 7. 获取所有请求记录
har_data = proxy.har # 返回一个字典,包含所有请求信息
# 示例:打印所有请求的 URL
for entry in har_data['log']['entries']:
print(entry['request']['url'])
# 8. 关闭浏览器和代理服务
driver.quit()
server.stop()
重要提示
-
JDK 17 完全兼容,无需降级。如果运行时提示 Java 找不到,请确保 JDK 的
bin目录已添加到系统 PATH,或者在命令行能执行java -version。 -
路径中的反斜杠:在 Python 字符串中,建议使用双反斜杠
\\或原始字符串r"D:\browsermob-proxy-2.1.4\bin\browsermob-proxy.bat"。 -
代理生效:
chrome_options.add_argument(f'--proxy-server={proxy.proxy}')中的proxy.proxy会自动返回类似localhost:8080的地址。 -
抓取内容:通过
proxy.har可以获得所有请求的 URL、请求头、响应体等,非常适合抓取 Canvas 渲染所需的数据接口。
更多推荐

所有评论(0)