4、表单交互:输入框、按钮、下拉框、单选/复选框的自动化操作

表单,说白了就是网页跟用户「要数据」的地方。登录、注册、搜索、下单……你想想看,几乎每个网站都离不开它。做自动化测试时,表单交互是绕不开的核心技能。

我个人习惯把表单操作分成四类:输入框、按钮、下拉框、单选/复选框。今天咱们一个一个来拆解。

4.1 输入框:最基础也最容易翻车

输入框的操作,看起来就是 send_keys() 完事。但我在项目中遇到过不少坑,比如输入框有默认值、有字符限制、或者需要先清空再输入。

先看最标准的写法:

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get("https://example.com/login")

# 找到用户名输入框
username_input = driver.find_element(By.ID, "username")
username_input.clear()  # 先清空,防止有默认值
username_input.send_keys("test_user")

# 密码输入框
password_input = driver.find_element(By.NAME, "password")
password_input.send_keys("mypassword123")

嗯,这里要注意:clear() 不是万能的。有些前端框架(比如 React、Vue)绑定了状态,clear() 清不掉。我曾经遇到过这种情况,折腾了半天才发现要用 send_keys(Keys.CONTROL + 'a') 全选再删除。

我的小技巧:遇到清不掉的情况,试试先点击输入框,然后发送 Keys.CONTROL + 'a' 全选,再发送 Keys.BACKSPACE 删除。这招在 90% 的场景下都管用。

4.2 按钮:别只盯着 click()

按钮操作,大家第一反应就是 click()。但说实话,很多按钮不是你想点就能点的。

常见问题:

  • 按钮被遮住了(弹窗、广告、固定导航栏)
  • 按钮是 disabled 状态
  • 按钮需要先滚动到可视区域

我的做法是:

from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# 等待按钮可点击
submit_btn = WebDriverWait(driver, 10).until(
    EC.element_to_be_clickable((By.ID, "submit-btn"))
)

# 方法1:直接点击
submit_btn.click()

# 方法2:如果直接点击报错,用 ActionChains
ActionChains(driver).move_to_element(submit_btn).click().perform()

# 方法3:用 JavaScript 点击(终极方案)
driver.execute_script("arguments[0].click();", submit_btn)
避坑指南:我曾经在某个后台管理系统里,按钮明明显示可点击,但 click() 就是没反应。后来发现是前端用了 pointer-events: none 样式。这种情况只能用 JavaScript 点击绕过。

4.3 下拉框:Select 对象是你的好帮手

下拉框分两种:原生 <select> 和自定义下拉框。处理方式完全不同。

原生下拉框:

from selenium.webdriver.support.ui import Select

# 找到 select 元素
select_element = driver.find_element(By.ID, "city")
select = Select(select_element)

# 三种选择方式
select.select_by_index(1)        # 按索引(从0开始)
select.select_by_value("shanghai")  # 按 value 属性
select.select_by_visible_text("上海")  # 按显示文本

自定义下拉框:说白了就是一堆 <div><li> 模拟的。这种没法用 Select 对象,得手动模拟点击。

# 点击下拉框展开选项
dropdown = driver.find_element(By.CLASS_NAME, "dropdown-toggle")
dropdown.click()

# 等待选项出现,然后点击
option = WebDriverWait(driver, 5).until(
    EC.element_to_be_clickable((By.XPATH, "//li[text()='上海']"))
)
option.click()
我的经验:判断是原生还是自定义,直接看 HTML 源码。有 <select> 标签的就是原生,否则就是自定义。自定义下拉框的选项经常有延迟加载,一定要加显式等待。

4.4 单选/复选框:别被外观骗了

单选按钮(radio)和复选框(checkbox),操作方式其实一样——都是 click()。但有个关键点:你要先判断它是不是已经被选中了

# 找到单选按钮组
male_radio = driver.find_element(By.ID, "gender-male")
female_radio = driver.find_element(By.ID, "gender-female")

# 判断是否已选中
if not male_radio.is_selected():
    male_radio.click()

# 复选框同理
agree_checkbox = driver.find_element(By.NAME, "agree")
if not agree_checkbox.is_selected():
    agree_checkbox.click()

你可能会问:为什么不直接点?嗯,因为有些场景下,用户可能已经默认选中了某个选项,你再点一下反而会取消选中。这在编辑表单时特别常见。

注意:有些前端框架会把真正的 <input> 隐藏掉,用 <label><span> 来显示样式。这时候 is_selected() 可能返回 false,但实际已经选中了。我的建议是:直接点击 <label> 元素,它通常会关联到真正的 input。

4.5 综合实战:一个完整的表单自动化

来,咱们写一个完整的注册表单自动化脚本。把今天学的都用上:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait, Select
from selenium.webdriver.support import expected_conditions as EC
import time

driver = webdriver.Chrome()
driver.get("https://example.com/register")
driver.maximize_window()

# 1. 输入框
username = driver.find_element(By.ID, "username")
username.clear()
username.send_keys("new_user_2024")

email = driver.find_element(By.NAME, "email")
email.send_keys("user@example.com")

# 2. 下拉框(选择城市)
city_select = Select(driver.find_element(By.ID, "city"))
city_select.select_by_visible_text("北京")

# 3. 单选按钮(选择性别)
gender_male = driver.find_element(By.ID, "gender-male")
if not gender_male.is_selected():
    gender_male.click()

# 4. 复选框(同意协议)
agree = driver.find_element(By.NAME, "agree")
if not agree.is_selected():
    agree.click()

# 5. 提交按钮
submit_btn = WebDriverWait(driver, 10).until(
    EC.element_to_be_clickable((By.ID, "register-btn"))
)
submit_btn.click()

# 验证是否注册成功
success_msg = WebDriverWait(driver, 5).until(
    EC.presence_of_element_located((By.CLASS_NAME, "success-message"))
)
print(f"注册结果:{success_msg.text}")

time.sleep(2)
driver.quit()

4.6 常见问题与避坑总结

问题 原因 解决方案
输入框输入后内容不对 有默认值或前端框架绑定 先 clear(),或用全选删除
按钮点击无反应 被遮挡或 disabled 用 ActionChains 或 JS 点击
下拉框选项找不到 选项是动态加载的 加显式等待,等选项出现
复选框选中状态不对 隐藏 input 导致 is_selected() 失效 直接点击 label 元素

核心要点:

  • 操作前先判断状态(是否选中、是否可点击)
  • 能用显式等待就别用 sleep()
  • 遇到前端框架封装,多用 JavaScript 兜底
  • 每次操作后加个断言,确保操作生效

表单交互这块,说白了就是「找到元素 → 判断状态 → 执行操作 → 验证结果」这四个步骤。你想想看,是不是所有表单操作都能套进这个框架里?

我个人觉得,自动化测试最难的不是写代码,而是处理各种前端框架的「小脾气」。多踩几次坑,你就知道该怎么应对了。下次遇到奇怪的表单问题,记得回来翻翻这篇笔记。