【Python自动化测试】Selenium常用函数详解

目录

自动化测试常用函数详解(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,使得自动化测试开发更加高效。关键点总结:

核心要点:

  1. 灵活选择定位方式:CSS Selector性能好,XPath功能强
  2. 合理使用等待机制:显式等待为主,避免强制等待
  3. 正确处理异常:添加适当的异常处理和日志记录
  4. 优化浏览器配置:根据测试需求调整参数
  5. 采用设计模式:如Page Object模式提高代码可维护性

调试技巧:

  1. 使用screenshot()记录失败场景
  2. 添加详细的日志输出
  3. 使用highlight_element()可视化操作元素
  4. 设置合理的超时时间

性能优化:

  1. 选择合适的页面加载策略
  2. 合理使用无头模式
  3. 避免不必要的等待
  4. 重用浏览器会话

通过掌握这些常用函数和最佳实践,可以构建出稳定、高效、易维护的Python自动化测试框架。

相关推荐
卜锦元3 小时前
Golang项目开发过程中好用的包整理归纳(附带不同包仓库地址)
开发语言·后端·golang
Tony Bai7 小时前
“我曾想付钱给 Google 去工作”—— Russ Cox 深度访谈:Go 的诞生、演进与未来
开发语言·后端·golang
sali-tec7 小时前
C# 基于halcon的视觉工作流-章66 四目匹配
开发语言·人工智能·数码相机·算法·计算机视觉·c#
路边草随风7 小时前
milvus向量数据库使用尝试
人工智能·python·milvus
hnlgzb7 小时前
安卓app开发,如何快速上手kotlin和compose的开发?
android·开发语言·kotlin
newobut7 小时前
vscode远程调试python程序,基于debugpy库
vscode·python·调试·debugpy
无敌最俊朗@8 小时前
STL-deque面试剖析(面试复习4)
开发语言
APIshop8 小时前
用 Python 把“API 接口”当数据源——从找口子到落库的全流程实战
开发语言·python
Java Fans8 小时前
Qt Designer 和 PyQt 开发教程
开发语言·qt·pyqt