目录
- 自动化测试常用函数详解(Python版)
-
- 一、元素定位:自动化测试的核心基础
-
- [1.1 CSS Selector](#1.1 CSS Selector)
- [1.2 XPath定位](#1.2 XPath定位)
- [1.3 其他定位方式](#1.3 其他定位方式)
- [1.4 定位最佳实践](#1.4 定位最佳实践)
- 二、测试对象操作:模拟真实用户交互
-
- [2.1 基本操作函数](#2.1 基本操作函数)
- [2.2 页面信息获取](#2.2 页面信息获取)
- [2.3 高级元素操作](#2.3 高级元素操作)
- 三、窗口管理:处理多窗口场景
-
- [3.1 窗口切换机制](#3.1 窗口切换机制)
- [3.2 窗口控制函数](#3.2 窗口控制函数)
- [3.3 截图与关闭](#3.3 截图与关闭)
- 四、弹窗处理:应对特殊交互场景
-
- [4.1 弹窗类型及处理](#4.1 弹窗类型及处理)
- [4.2 复杂弹窗处理](#4.2 复杂弹窗处理)
- 五、等待策略:确保测试稳定性
-
- [5.1 三种等待方式对比](#5.1 三种等待方式对比)
- [5.2 常用ExpectedConditions](#5.2 常用ExpectedConditions)
- [5.3 等待最佳实践](#5.3 等待最佳实践)
- 六、浏览器导航与文件上传
-
- [6.1 页面导航](#6.1 页面导航)
- [6.2 文件上传](#6.2 文件上传)
- 七、浏览器参数配置
-
- [7.1 Edge浏览器配置](#7.1 Edge浏览器配置)
- [7.2 其他浏览器配置](#7.2 其他浏览器配置)
- [7.3 页面加载策略详解](#7.3 页面加载策略详解)
自动化测试常用函数详解(Python版)
一、元素定位:自动化测试的核心基础
1.1 CSS Selector
CSS选择器是Web自动化测试中最常用的元素定位方式,通过CSS语法规则定位页面元素。
python
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
# 初始化驱动
driver = webdriver.Chrome()
# ID选择器
search_box = driver.find_element(By.CSS_SELECTOR, "#kw")
search_button = driver.find_element(By.CSS_SELECTOR, "#su")
# 类选择器
hot_item = driver.find_element(By.CSS_SELECTOR, ".hotsearch-item")
# 属性选择器
input_element = driver.find_element(By.CSS_SELECTOR, "input[name='username']")
# 子元素选择器
wrapper_content = driver.find_element(By.CSS_SELECTOR, "#s-hotsearch-wrapper > div")
# 组合选择器
news_link = driver.find_element(By.CSS_SELECTOR, "a[href*='news'].title-content")
1.2 XPath定位
XPath功能强大,适用于复杂定位场景。
python
# 基本定位
all_elements = driver.find_elements(By.XPATH, "//*")
all_inputs = driver.find_elements(By.XPATH, "//input")
# 属性定位
search_input = driver.find_element(By.XPATH, "//*[@id='kw']")
password_field = driver.find_element(By.XPATH, "//input[@type='password']")
# 文本内容定位
hot_search = driver.find_element(By.XPATH, "//span[contains(text(), '热搜')]")
exact_text = driver.find_element(By.XPATH, "//button[text()='提交']")
# 索引定位(注意:XPath索引从1开始)
third_item = driver.find_element(By.XPATH, "//div/ul/li[3]")
first_span = driver.find_element(By.XPATH, "//*[@id='hotsearch-content-wrapper']/li[1]/a/span[2]")
# 相对路径
child_element = driver.find_element(By.XPATH, "//div//input")
parent_element = driver.find_element(By.XPATH, "//input/..")
# 多条件组合
complex_element = driver.find_element(By.XPATH, "//div[@class='container' and @id='main']//a[@href='#' and @class='link']")
1.3 其他定位方式
python
# ID定位(最快速)
element = driver.find_element(By.ID, "username")
# Name定位
element = driver.find_element(By.NAME, "password")
# Class Name定位
elements = driver.find_elements(By.CLASS_NAME, "btn-primary")
# Tag Name定位
links = driver.find_elements(By.TAG_NAME, "a")
# Link Text定位(完全匹配)
link = driver.find_element(By.LINK_TEXT, "百度首页")
# Partial Link Text定位(部分匹配)
link = driver.find_element(By.PARTIAL_LINK_TEXT, "百度")
1.4 定位最佳实践
python
def find_element_safely(driver, by, value, timeout=10):
"""安全查找元素,带等待机制"""
try:
element = WebDriverWait(driver, timeout).until(
EC.presence_of_element_located((by, value))
)
return element
except Exception as e:
print(f"元素定位失败: {by}={value}, 错误: {e}")
return None
# 使用示例
element = find_element_safely(driver, By.CSS_SELECTOR, "#kw")
if element:
element.send_keys("自动化测试")
二、测试对象操作:模拟真实用户交互
2.1 基本操作函数
python
# 点击操作
search_button = driver.find_element(By.CSS_SELECTOR, "#su")
search_button.click()
# 文本输入
search_box = driver.find_element(By.CSS_SELECTOR, "#kw")
search_box.send_keys("Python自动化测试")
# 清除内容
search_box.clear()
search_box.send_keys("Selenium WebDriver")
# 模拟键盘操作
from selenium.webdriver.common.keys import Keys
search_box.send_keys(Keys.CONTROL + 'a') # 全选
search_box.send_keys(Keys.DELETE) # 删除
search_box.send_keys("新的内容")
search_box.send_keys(Keys.ENTER) # 回车
# 获取元素文本
hot_text = driver.find_element(
By.XPATH, '//*[@id="hotsearch-content-wrapper"]/li[1]/a/span[2]'
).text
print(f"热搜文本: {hot_text}")
# 获取元素属性
button_value = driver.find_element(By.CSS_SELECTOR, "#su").get_attribute("value")
print(f"按钮文本: {button_value}")
# 检查元素状态
element = driver.find_element(By.CSS_SELECTOR, "#kw")
print(f"是否可见: {element.is_displayed()}")
print(f"是否启用: {element.is_enabled()}")
print(f"是否选中: {element.is_selected()}")
# 提交表单
form = driver.find_element(By.CSS_SELECTOR, "form")
form.submit()
2.2 页面信息获取
python
# 获取页面标题
title = driver.title
print(f"页面标题: {title}")
# 获取当前URL
current_url = driver.current_url
print(f"当前URL: {current_url}")
# 获取页面源代码
page_source = driver.page_source
# 获取cookie
cookies = driver.get_cookies()
for cookie in cookies:
print(f"Cookie: {cookie['name']} = {cookie['value']}")
# 添加cookie
driver.add_cookie({'name': 'test_cookie', 'value': 'test_value'})
# 删除cookie
driver.delete_cookie('test_cookie')
driver.delete_all_cookies()
2.3 高级元素操作
python
# 鼠标悬停
from selenium.webdriver.common.action_chains import ActionChains
element = driver.find_element(By.CSS_SELECTOR, ".dropdown")
actions = ActionChains(driver)
actions.move_to_element(element).perform()
# 双击操作
actions.double_click(element).perform()
# 右键点击
actions.context_click(element).perform()
# 拖拽操作
source = driver.find_element(By.ID, "draggable")
target = driver.find_element(By.ID, "droppable")
actions.drag_and_drop(source, target).perform()
三、窗口管理:处理多窗口场景
3.1 窗口切换机制
python
# 获取当前窗口句柄
current_handle = driver.current_window_handle
print(f"当前窗口句柄: {current_handle}")
# 获取所有窗口句柄
all_handles = driver.window_handles
print(f"所有窗口句柄: {all_handles}")
# 打开新窗口
driver.execute_script("window.open('https://www.google.com')")
# 切换到最新窗口
new_handles = driver.window_handles
for handle in new_handles:
if handle != current_handle:
driver.switch_to.window(handle)
break
# 切换到指定窗口
driver.switch_to.window(all_handles[1]) # 切换到第二个窗口
# 遍历所有窗口
for handle in driver.window_handles:
driver.switch_to.window(handle)
print(f"窗口标题: {driver.title}")
3.2 窗口控制函数
python
# 窗口最大化
driver.maximize_window()
# 窗口最小化
driver.minimize_window()
# 窗口全屏
driver.fullscreen_window()
# 设置窗口大小
driver.set_window_size(1024, 768)
# 设置窗口位置
driver.set_window_position(100, 100)
# 获取窗口信息
size = driver.get_window_size()
print(f"窗口大小: {size}")
position = driver.get_window_position()
print(f"窗口位置: {position}")
rect = driver.get_window_rect() # 同时获取位置和大小
print(f"窗口矩形: {rect}")
3.3 截图与关闭
python
import time
from datetime import datetime
import os
# 创建截图目录
screenshot_dir = "screenshots"
os.makedirs(screenshot_dir, exist_ok=True)
# 基础截图
driver.save_screenshot(f"{screenshot_dir}/screenshot.png")
# 带时间戳的截图
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
filename = f"{screenshot_dir}/autotest_{timestamp}.png"
driver.save_screenshot(filename)
print(f"截图保存到: {filename}")
# 元素截图
element = driver.find_element(By.CSS_SELECTOR, "#kw")
element.screenshot(f"{screenshot_dir}/element_{timestamp}.png")
# 关闭窗口
driver.close() # 关闭当前窗口
driver.quit() # 关闭所有窗口并退出驱动
四、弹窗处理:应对特殊交互场景
4.1 弹窗类型及处理
python
# 切换到弹窗
alert = driver.switch_to.alert
# 获取弹窗文本
alert_text = alert.text
print(f"弹窗文本: {alert_text}")
# 警告/确认弹窗处理
alert.accept() # 点击确定/确认
# 或
alert.dismiss() # 点击取消/关闭
# 提示弹窗(可输入文本)
alert.send_keys("输入内容")
alert.accept() # 确认输入
# 处理JavaScript弹窗示例
driver.execute_script("alert('这是一个测试弹窗');")
time.sleep(1)
alert = driver.switch_to.alert
print(f"弹窗内容: {alert.text}")
alert.accept()
4.2 复杂弹窗处理
python
# 处理iframe中的弹窗
driver.switch_to.frame("iframe_name_or_id")
# 处理iframe内的弹窗...
driver.switch_to.default_content() # 切换回主文档
# 检查弹窗是否存在
def is_alert_present(driver, timeout=3):
"""检查弹窗是否存在"""
try:
WebDriverWait(driver, timeout).until(EC.alert_is_present())
return True
except:
return False
# 安全处理弹窗
def handle_alert_safely(driver, accept=True, input_text=None):
"""安全处理弹窗"""
try:
alert = driver.switch_to.alert
if input_text:
alert.send_keys(input_text)
if accept:
alert.accept()
else:
alert.dismiss()
return True
except:
return False
五、等待策略:确保测试稳定性
5.1 三种等待方式对比
python
import time
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
# 1. 强制等待(不推荐在生产环境使用)
print("等待3秒...")
time.sleep(3)
# 2. 隐式等待(全局设置)
driver.implicitly_wait(10) # 单位:秒
# 注意:设置一次,对driver生命周期内所有find_element操作生效
# 3. 显式等待(推荐使用)
# 创建等待对象
wait = WebDriverWait(driver, 10) # 最多等待10秒
# 等待元素可见
element = wait.until(
EC.visibility_of_element_located((By.ID, "myElement"))
)
# 等待元素可点击
clickable_element = wait.until(
EC.element_to_be_clickable((By.CSS_SELECTOR, "#submit"))
)
clickable_element.click()
5.2 常用ExpectedConditions
python
# 元素可见性
wait.until(EC.visibility_of_element_located((By.ID, "element_id")))
wait.until(EC.visibility_of_all_elements_located((By.CLASS_NAME, "items")))
# 元素存在(不一定可见)
wait.until(EC.presence_of_element_located((By.ID, "element_id")))
# 元素不可见
wait.until(EC.invisibility_of_element_located((By.ID, "loading")))
# 元素包含特定文本
wait.until(EC.text_to_be_present_in_element((By.ID, "status"), "完成"))
# 元素属性包含特定值
wait.until(EC.text_to_be_present_in_element_attribute(
(By.ID, "input"), "value", "expected_text"
))
# 标题检查
wait.until(EC.title_is("期望的标题"))
wait.until(EC.title_contains("部分标题"))
# URL检查
wait.until(EC.url_to_be("https://www.example.com"))
wait.until(EC.url_contains("example"))
# 弹窗检查
wait.until(EC.alert_is_present())
# 框架可用性
wait.until(EC.frame_to_be_available_and_switch_to_it("frame_name"))
# 自定义等待条件
def element_has_class(element, class_name):
"""自定义条件:检查元素是否包含特定class"""
def predicate(driver):
return class_name in element.get_attribute("class")
return predicate
# 使用自定义条件
element = driver.find_element(By.ID, "myElement")
wait.until(element_has_class(element, "active"))
5.3 等待最佳实践
python
class SmartWait:
"""智能等待工具类"""
def __init__(self, driver, timeout=30, poll_frequency=0.5):
self.driver = driver
self.timeout = timeout
self.wait = WebDriverWait(driver, timeout, poll_frequency=poll_frequency)
def wait_for_element(self, locator, visible=True):
"""等待元素"""
try:
if visible:
return self.wait.until(
EC.visibility_of_element_located(locator)
)
else:
return self.wait.until(
EC.presence_of_element_located(locator)
)
except TimeoutException:
print(f"等待元素超时: {locator}")
return None
def wait_for_clickable(self, locator):
"""等待元素可点击"""
try:
return self.wait.until(
EC.element_to_be_clickable(locator)
)
except TimeoutException:
print(f"等待元素可点击超时: {locator}")
return None
def wait_for_page_load(self):
"""等待页面加载完成"""
try:
self.wait.until(
lambda d: d.execute_script("return document.readyState") == "complete"
)
except TimeoutException:
print("页面加载超时")
# 使用示例
smart_wait = SmartWait(driver)
element = smart_wait.wait_for_element((By.ID, "username"))
if element:
element.send_keys("testuser")
六、浏览器导航与文件上传
6.1 页面导航
python
# 打开网页
driver.get("https://www.baidu.com")
# 浏览器导航
driver.back() # 后退
driver.forward() # 前进
driver.refresh() # 刷新
# 获取浏览器历史记录长度(通过JavaScript)
history_length = driver.execute_script("return window.history.length")
print(f"历史记录长度: {history_length}")
# 导航案例:测试页面跳转
def test_navigation():
driver.get("https://www.baidu.com")
# 点击新闻链接
news_link = driver.find_element(By.LINK_TEXT, "新闻")
news_link.click()
# 等待新页面加载
WebDriverWait(driver, 10).until(
EC.title_contains("新闻")
)
# 后退到百度首页
driver.back()
# 验证回到百度首页
assert "百度一下" in driver.title
# 前进回到新闻页
driver.forward()
print("导航测试完成")
6.2 文件上传
python
import os
# 方法1:使用send_keys直接上传
file_input = driver.find_element(By.CSS_SELECTOR, "input[type='file']")
# 上传单个文件
current_dir = os.path.dirname(os.path.abspath(__file__))
file_path = os.path.join(current_dir, "test_files", "test.txt")
file_input.send_keys(file_path)
# 上传多个文件
file1 = os.path.join(current_dir, "test_files", "file1.txt")
file2 = os.path.join(current_dir, "test_files", "file2.jpg")
file_input.send_keys(f"{file1}\n{file2}") # 使用换行符分隔
# 方法2:使用AutoIT或PyAutoGUI处理系统弹窗(如果需要)
# 注意:Selenium无法直接操作Windows/Mac的文件选择对话框
# 方法3:使用JavaScript绕过文件选择对话框
def upload_file_via_js(driver, element, file_path):
"""通过JavaScript上传文件"""
driver.execute_script("""
arguments[0].style.display = 'block';
arguments[0].style.visibility = 'visible';
""", element)
# 设置文件路径
driver.execute_script(f"""
var element = arguments[0];
element.value = '{file_path}';
element.dispatchEvent(new Event('change', {{ bubbles: true }}));
""", element)
# 文件上传示例
def test_file_upload():
driver.get("https://www.file-upload-test.com")
# 找到文件上传元素
upload_element = driver.find_element(By.ID, "file-upload")
# 获取当前脚本所在目录
current_dir = os.path.dirname(os.path.abspath(__file__))
# 上传测试文件
test_file = os.path.join(current_dir, "data", "test_document.pdf")
if os.path.exists(test_file):
upload_element.send_keys(test_file)
print(f"已上传文件: {test_file}")
# 提交表单
submit_button = driver.find_element(By.ID, "submit-btn")
submit_button.click()
# 验证上传成功
success_message = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.CLASS_NAME, "success-message"))
)
print(f"上传结果: {success_message.text}")
else:
print(f"文件不存在: {test_file}")
七、浏览器参数配置
7.1 Edge浏览器配置
python
import time
from selenium import webdriver
from selenium.webdriver.edge.service import Service
from selenium.webdriver.edge.options import Options
# from webdriver_manager.edge import EdgeDriverManager
def create_edge_driver(headless=False, options=None):
"""创建 Edge 浏览器驱动"""
if options is None:
options = Options()
# options = webdriver.EdgeOptions()
# 无头模式
if headless:
options.add_argument("--headless")
# 常用配置参数
edge_options = [
"--disable-gpu", # 禁用GPU加速
"--no-sandbox", # 禁用沙箱(Linux环境需要)
"--disable-dev-shm-usage", # 解决资源限制问题
"--disable-blink-features=AutomationControlled", # 隐藏自动化特征
"--disable-infobars", # 禁用信息栏
"--disable-notifications", # 禁用通知
f"--window-size=1920,1080", # 设置窗口大小
]
for option in edge_options:
options.add_argument(option)
# 实验性选项
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
# 设置页面加载策略
options.page_load_strategy = 'normal' # normal, eager, none
# 禁用密码管理器弹窗
prefs = {
"credentials_enable_service": False,
"profile.password_manager_enabled": False,
"profile.default_content_setting_values.notifications": 2
}
options.add_experimental_option("prefs", prefs)
# 使用webdriver-manager自动管理驱动
# service = Service(ChromeDriverManager().install())
#edge_driver_path = r"C:\Users\tangi\AppData\Local\Programs\Python\Python312\msedgedriver.exe"
# # # 创建驱动服务
#service = Service(edge_driver_path)
# 创建驱动
driver = webdriver.Edge(options=options)
# 执行CDP命令,隐藏WebDriver特征
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
'source': '''
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
})
'''
})
return driver
# 使用示例
driver = create_edge_driver(headless=False)
driver.get("https://www.baidu.com")
#time.sleep(3)
print(f"页面标题: {driver.title}")
driver.quit()
7.2 其他浏览器配置
python
# Firefox配置
from selenium.webdriver import Firefox
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.firefox.service import Service
from webdriver_manager.firefox import GeckoDriverManager
firefox_options = Options()
firefox_options.add_argument("--headless")
firefox_options.add_argument("--width=1920")
firefox_options.add_argument("--height=1080")
service = Service(GeckoDriverManager().install())
firefox_driver = Firefox(service=service, options=firefox_options)
# Edge配置
from selenium.webdriver import Edge
from selenium.webdriver.edge.options import Options
from selenium.webdriver.edge.service import Service
from webdriver_manager.microsoft import EdgeChromiumDriverManager
edge_options = Options()
edge_options.add_argument("--headless")
edge_options.add_argument("--disable-gpu")
service = Service(EdgeChromiumDriverManager().install())
edge_driver = Edge(service=service, options=edge_options)
7.3 页面加载策略详解
⻚⾯加载策略:
python
options.page_load_strategy = '加载方式'
页面加载方式主要有三种类型:
| 策略 | 说明 |
|---|---|
| normal | 默认值,等待所有资源下载 |
| eager | DOM访问已准备就绪,但诸如图像的其他资源可能仍在加载 |
| none | 完全不会阻塞WebDriver |
使用示例:
python
options = webdriver.ChromeOptions()
options.page_load_strategy = 'eager'
driver = webdriver.Chrome(
service=ChromeService
```python
# 三种页面加载策略
def test_page_load_strategies():
"""测试不同的页面加载策略"""
strategies = ['normal', 'eager', 'none']
for strategy in strategies:
print(f"\n测试加载策略: {strategy}")
options = Options()
options.page_load_strategy = strategy
driver = webdriver.Chrome(options=options)
start_time = time.time()
driver.get("https://www.example.com")
load_time = time.time() - start_time
print(f"加载时间: {load_time:.2f}秒")
print(f"页面标题: {driver.title}")
driver.quit()
# 使用不同加载策略的示例
def create_driver_with_strategy(strategy='normal'):
"""根据策略创建驱动"""
options = Options()
options.page_load_strategy = strategy
if strategy == 'eager':
# eager模式下的额外配置
options.add_argument("--disable-images")
options.add_argument("--disable-stylesheets")
return webdriver.Chrome(options=options)
总结
Python版的Selenium WebDriver提供了丰富而简洁的API,使得自动化测试开发更加高效。关键点总结:
核心要点:
- 灵活选择定位方式:CSS Selector性能好,XPath功能强
- 合理使用等待机制:显式等待为主,避免强制等待
- 正确处理异常:添加适当的异常处理和日志记录
- 优化浏览器配置:根据测试需求调整参数
- 采用设计模式:如Page Object模式提高代码可维护性
调试技巧:
- 使用
screenshot()记录失败场景 - 添加详细的日志输出
- 使用
highlight_element()可视化操作元素 - 设置合理的超时时间
性能优化:
- 选择合适的页面加载策略
- 合理使用无头模式
- 避免不必要的等待
- 重用浏览器会话
通过掌握这些常用函数和最佳实践,可以构建出稳定、高效、易维护的Python自动化测试框架。