作为一名长期从事Web自动化测试的工程师,我见证了Selenium从一个小众工具成长为行业标准的过程。Selenium之所以能在众多测试框架中脱颖而出,关键在于它完美模拟了真实用户的操作行为,让自动化测试变得前所未有的直观和可靠。
Selenium本质上是一个浏览器自动化操作框架,它通过直接控制浏览器来执行测试脚本,就像真实用户在操作一样。这种设计理念带来了几个不可替代的优势:
提示:Selenium 4.x版本已经全面支持W3C WebDriver标准,解决了不同浏览器驱动兼容性问题,建议新项目直接使用最新版本。
完整的Selenium生态系统包含多个组件:
| 组件名称 | 功能描述 |
|---|---|
| Selenium WebDriver | 核心组件,提供操作浏览器的API接口 |
| Selenium IDE | 录制回放工具,适合快速创建简单测试用例 |
| Selenium Grid | 分布式测试解决方案,支持并行执行测试用例 |
| Selenium Client | 各种编程语言的客户端库(Python/Java等) |
推荐使用Python 3.7+版本,通过pip安装Selenium包:
bash复制pip install selenium
不同浏览器需要对应的驱动程序:
以Chrome为例,驱动配置步骤:
常见问题:版本不匹配会导致驱动无法正常工作,必须确保浏览器版本与驱动版本一致
python复制from selenium import webdriver
# 创建浏览器实例
driver = webdriver.Chrome()
# 打开网页
driver.get("https://www.baidu.com")
# 定位搜索框并输入关键词
search_box = driver.find_element_by_id("kw")
search_box.send_keys("Selenium自动化测试")
# 定位搜索按钮并点击
search_button = driver.find_element_by_id("su")
search_button.click()
# 关闭浏览器
driver.quit()
Selenium提供了多种元素定位方式:
find_element_by_id()find_element_by_name()find_element_by_class_name()find_element_by_tag_name()find_element_by_link_text()find_element_by_partial_link_text()find_element_by_xpath()find_element_by_css_selector()XPath是功能最强大的定位方式,常见用法:
python复制# 绝对路径定位
driver.find_element_by_xpath("/html/body/div[1]/div[2]/div[1]/input")
# 相对路径+属性定位
driver.find_element_by_xpath("//input[@id='kw']")
# 文本内容定位
driver.find_element_by_xpath("//a[contains(text(),'登录')]")
# 多条件组合
driver.find_element_by_xpath("//input[@type='text' and @name='username']")
CSS选择器定位效率通常比XPath更高:
python复制# ID选择器
driver.find_element_by_css_selector("#kw")
# Class选择器
driver.find_element_by_css_selector(".s_ipt")
# 属性选择器
driver.find_element_by_css_selector("[name='wd']")
# 组合选择器
driver.find_element_by_css_selector("form#form>span>input.s_ipt")
python复制# 浏览器导航
driver.back() # 后退
driver.forward() # 前进
driver.refresh() # 刷新
# 窗口操作
driver.maximize_window() # 最大化窗口
driver.set_window_size(1200, 800) # 设置窗口大小
driver.get_window_position() # 获取窗口位置
# 页面信息获取
driver.title # 获取标题
driver.current_url # 获取当前URL
driver.page_source # 获取页面源码
python复制# 输入框操作
element = driver.find_element_by_id("username")
element.clear() # 清空输入框
element.send_keys("testuser") # 输入文本
# 单选框/复选框操作
checkbox = driver.find_element_by_name("remember")
checkbox.click() # 切换选中状态
# 下拉框选择
from selenium.webdriver.support.ui import Select
select = Select(driver.find_element_by_id("city"))
select.select_by_value("beijing") # 按value选择
select.select_by_visible_text("北京") # 按文本选择
python复制# 普通文件上传
upload = driver.find_element_by_name("file")
upload.send_keys("/path/to/file.txt")
# 隐藏的文件输入框(需要JS注入)
driver.execute_script("document.querySelector('input[type=file]').style.display='block';")
upload = driver.find_element_by_css_selector("input[type=file]")
upload.send_keys("/path/to/file.txt")
用于模拟复杂鼠标操作:
python复制from selenium.webdriver import ActionChains
element = driver.find_element_by_id("draggable")
target = driver.find_element_by_id("droppable")
actions = ActionChains(driver)
actions.drag_and_drop(element, target).perform()
# 其他常用动作
actions.click_and_hold(element).move_to_element(target).release().perform()
actions.context_click(element).perform() # 右键点击
actions.double_click(element).perform() # 双击
python复制# 执行JS脚本
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
# 修改元素属性
driver.execute_script("arguments[0].setAttribute('style', 'display: block;')", element)
# 获取返回值
value = driver.execute_script("return document.title")
python复制driver.implicitly_wait(10) # 最多等待10秒
python复制from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
wait = WebDriverWait(driver, 10)
element = wait.until(EC.presence_of_element_located((By.ID, "dynamicElement")))
常用等待条件:
| 条件 | 描述 |
|---|---|
| presence_of_element_located | 元素出现在DOM中 |
| visibility_of_element_located | 元素可见 |
| element_to_be_clickable | 元素可点击 |
| text_to_be_present_in_element | 元素包含特定文本 |
| frame_to_be_available_and_switch_to_it | frame可用并切换进去 |
python复制class LoginPage:
def __init__(self, driver):
self.driver = driver
self.username = (By.ID, "username")
self.password = (By.ID, "password")
self.submit = (By.ID, "submit")
def enter_username(self, text):
self.driver.find_element(*self.username).send_keys(text)
def enter_password(self, text):
self.driver.find_element(*self.password).send_keys(text)
def click_submit(self):
self.driver.find_element(*self.submit).click()
# 使用示例
login_page = LoginPage(driver)
login_page.enter_username("admin")
login_page.enter_password("123456")
login_page.click_submit()
结合pytest实现:
python复制import pytest
test_data = [
("admin", "123456", True),
("test", "wrong", False)
]
@pytest.mark.parametrize("username,password,expected", test_data)
def test_login(username, password, expected):
login_page = LoginPage(driver)
login_page.enter_username(username)
login_page.enter_password(password)
login_page.click_submit()
if expected:
assert "Dashboard" in driver.title
else:
assert "Login Failed" in driver.page_source
使用Allure生成美观报告:
python复制import allure
@allure.feature("登录测试")
class TestLogin:
@allure.story("成功登录")
def test_success_login(self):
with allure.step("输入用户名密码"):
login_page.enter_username("admin")
login_page.enter_password("123456")
with allure.step("点击登录按钮"):
login_page.click_submit()
with allure.step("验证登录结果"):
assert "Dashboard" in driver.title
常见原因:
解决方案:
python复制try:
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.XPATH, "//button[text()='Submit']"))
)
except TimeoutException:
print("元素定位失败,尝试备用方案...")
driver.save_screenshot("error.png") # 保存截图
python复制from selenium.webdriver.chrome.options import Options
chrome_options = Options()
chrome_options.add_argument("--headless") # 无头模式
chrome_options.add_argument("--disable-gpu") # 禁用GPU加速
chrome_options.add_argument("--no-sandbox") # Linux系统需要
driver = webdriver.Chrome(options=chrome_options)
使用Selenium Grid搭建:
java复制# 启动Hub
java -jar selenium-server-standalone.jar -role hub
# 启动Node
java -jar selenium-server-standalone.jar -role node -hub http://hub-ip:4444/grid/register
Python客户端配置:
python复制from selenium import webdriver
capabilities = {
"browserName": "chrome",
"version": "latest",
"platform": "WINDOWS"
}
driver = webdriver.Remote(
command_executor="http://hub-ip:4444/wd/hub",
desired_capabilities=capabilities
)
通过Appium集成:
python复制from appium import webdriver
desired_caps = {
'platformName': 'Android',
'deviceName': 'emulator-5554',
'app': '/path/to/app.apk'
}
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
python复制from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
caps = DesiredCapabilities.CHROME
caps['loggingPrefs'] = {'performance': 'ALL'}
driver = webdriver.Chrome(desired_capabilities=caps)
# 获取性能日志
for entry in driver.get_log('performance'):
print(entry)
在实际项目中,Selenium已经成为我们质量保障体系中不可或缺的一环。通过合理的框架设计和持续优化,我们成功将UI自动化测试覆盖率提升到了80%以上,回归测试时间从原来的3天缩短到2小时。记住,好的自动化测试不是一蹴而就的,需要不断迭代和完善。