web自动化知识_ccf备赛版
//直接从我的文档copy'的所以有点乱,这个为自己的学习总结
Web自动化知识
-
考前准备
Pip install pytest
Pip install selenium
Pip install selenium.webdriver.(显示等待)
生成 requirements.txt 文件
安装好所有依赖包后,可以使用以下命令生成 requirements.txt 文件。
pip freeze >requirements.txt
这条命令会将当前虚拟环境中的所有已安装包及其版本信息输出到requirements.txt 文件中。
使用 requirements.txt 文件安装依赖
在新的环境或其他开发人员的机器上,可以使用requirements.txt 文件来安装项目的所有依赖包。
首先,确保激活虚拟环境,然后运行以下命令:
pip install -r requirements.txt
这条命令会读取 requirements.txt 文件并安装其中列出的所有依赖包。
环境搭建
#导包
#指定驱动服务更快速
import time
from selenium import webdriver
#创建浏览器对象
driver=webdriver.Chrome()
# 打开商品管理页面
driver.get("https://litemall.hogwarts.ceshiren.com/")
#页面最大化
driver.maximize_window()
time.sleep(5)
#关闭驱动
driver.quit()
-
元素定位及找不到怎么办
元素定位
name
driver.find_element(By.NAME,"password").clear()
id
driver.find_element(By.ID,"password")
LINK_TEXT(找不到元素试试直接中文)
driver.find_element(By.LINK_TEXT, "通讯录").click()
tag name
xpath
1.有明确文本的:driver.find_element(By.XPATH,"//*[text()='商品列表']")
2.输入框输入"//label[text()='商品编号']/following-sibling::div//input"
利用页面结构(label + 输入框)进行相对定位,非常稳定,适合表单输入
3.包含文本匹配://*[contains(text(), '商品')]
用途:查找文本中包含“商品”的任意元素。
- 部分匹配
✅ XPath 中的部分匹配函数
|
匹配类型 |
CSS Selector |
XPath |
|
以...开头 |
[attr^='value'] |
starts-with(@attr, 'value') |
|
以...结尾 |
[attr$='value'] |
ends-with(@attr, 'value') |
|
包含... |
[attr*='value'] |
contains(@attr, 'value') |
css_selector
id,#开头
class,.开头
部分匹配
self.driver.find_element(By.CSS_SELECTOR, "input[id^='user']") # id 以 user 开头 self.driver.find_element(By.CSS_SELECTOR, "input[id$='Name']") # id 以 Name 结尾# self.driver.find_element(By.CSS_SELECTOR, "input[class*='input']") # class 包含 input
calss_name(多个名选取其中一个)
PARTIAL_LINK_TEXT = "partial link text"
页面没有加载完成
显示等待
#下载 pip install selenium.webdriver.
#导入包
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
el = WebDriverWait(driver, 5).until(EC.presence_of_element_located((By.XPATH, '//* [@id="1"]/div/h3/a'))) # driver.find_element(By.XPATH, '//*[@id="1"]/div/h3/a').click() el.click()
隐式等待
driver.implicitly_wait(3)
强制等待
impot time Time.sleep()
框架内元素不可找
当元素在子页面的frame元素中需要进行切换定位
driver.switch_to.frame(driver.find_element(By.XPATH, '/html/frameset/frame[1]'))
//大框架frame的定位
driver.find_element(By.XPATH, '//*[@id="navs"]/ul/li[2]/a').//click()真正元素定位
元素变化
//*[@id="auto-id-ri6QaGIEhN3bTxsA"]
//*[@id="auto-id-ghlNbd98dkqJFidB"]
//*[@id="auto-id-4SCakBx15gzHDRud"]
# 定位以 auto-id- 开头的 id 元素
element = driver.find_element(By.XPATH, '//*[starts-with(@id, "auto-id-")]')
成功://*[@id="fanwe_success_box"]/table/tbody/tr/td[2]/div[2]
失败://*[@id="fanwe_error_box"]/table/tbody/tr/td[2]/div[2]
# 不管是正例和反例的提示信息都要进行获取
# 可以通过手写xpath以**开头进行定位
text = driver.find_element(By.XPATH, '//*[starts-
with(@id,"fanwe_")]/table/tbody/tr/td[2]/div[2]').text
//把变化的去掉留下固定的就好
转换路径法
当搜索按钮实在定位不到,可以用回车键替代
from selenium.webdriver.common.keys import Keys# 输入完直接按回车 = 搜索search_input = self.driver.find_element(By.CSS_SELECTOR,
'[placeholder="搜索"]')
search_input.send_keys(search_key)
search_input.send_keys(Keys.ENTER) # 回车触发搜索
- 断言知识
✅ 五、常见断言方法总结(Python)
|
断言方法 |
说明 |
|
assert x == y |
相等 |
|
assert x in y |
包含 |
|
assert x.startswith(y) |
以...开头 |
|
assert elem.is_displayed() |
元素可见 |
|
assert elem.is_enabled() |
元素可操作 |
|
self.assertEqual(a, b) |
unittest 相等断言 |
|
self.assertIn(a, b) |
unittest 包含断言 |
|
self.assertTrue(expr) |
表达式为真 |
列子:
assert "登录成功" in message, f"期望包含'登录成功',实际是:{message}"
6. 元素存
在性断言
检查某个元素是否存在(注意:不存在会抛异常)。
from selenium.common.exceptions
import NoSuchElementExceptiontry:
driver.find_element(By.ID, "logout-btn")
assert True # 找到了
except NoSuchElementException:
assert False, "未找到退出按钮"
4. 元素状态断言
检查元素是否可见、可点击、被选中等。
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
elem = driver.find_element(By.ID, "submit-btn")
# 是否可见
assert elem.is_displayed()
# 是否可点击
assert elem.is_enabled()
# 是否被选中(如复选框)
assert elem.is_selected()
# 使用 expected_conditions 做显式等待 + 断言
wait = WebDriverWait(driver, 10)
wait.until(EC.element_to_be_clickable((By.ID, "submit-btn")))
-
不同应用题模版
功能模块
- 切换页面
#切换窗口
handles=self.driver.window_handles#所有句柄
old_handles=self.driver.current_window_handle#当前句柄
self.driver.switch_to.window(handles[-1])#切换到最新的窗口
new_handles=self.driver.current_window_handle
print(f"所有句柄:{handles},切换前句柄:{old_handles},切换后句柄:{new_handles}")
- 页面截屏
# 截取当前页面的截图并保存到本地文件driver.save_screenshot('screenshot.png')
-
商品管理类
import unittest
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
from selenium.common.exceptions import TimeoutException, NoSuchElementException
import time
class TestProductManagement(unittest.TestCase):
"""商品管理自动化测试套件"""
def setUp(self):
"""测试前置条件:初始化浏览器和等待对象"""
self.driver = webdriver.Chrome() # 确保已安装ChromeDriver
self.driver.implicitly_wait(10) # 隐式等待
self.wait = WebDriverWait(self.driver, 10) # 显式等待
self.base_url = "https://your-ecommerce-site.com" # 替换为实际URL
def test_login_and_manage_products(self):
"""主测试流程:登录 -> 添加商品 -> 编辑商品 -> 删除商品"""
driver = self.driver
try:
# 1. 登录
self.login(driver)
# 2. 导航到商品管理页面
self.navigate_to_product_management(driver)
# 3. 添加新商品
product_name = f"Test Product {int(time.time())}" # 使用时间戳确保唯一性
product_price = "99.99"
self.add_product(driver, product_name, product_price)
# 4. 验证商品添加成功
self.verify_product_added(driver, product_name)
# 5. 编辑商品
new_price = "88.88"
self.edit_product(driver, product_name, new_price)
# 6. 验证商品编辑成功
self.verify_product_edited(driver, product_name, new_price)
# 7. 删除商品
self.delete_product(driver, product_name)
# 8. 验证商品删除成功
self.verify_product_deleted(driver, product_name)
except Exception as e:
self.fail(f"测试执行过程中发生异常: {str(e)}")
def login(self, driver):
"""执行登录操作"""
print("正在执行登录...")
driver.get(f"{self.base_url}/login")
# 等待页面加载并定位元素
username_input = self.wait.until(
EC.presence_of_element_located((By.ID, "username")) # 替换为实际定位符
)
password_input = driver.find_element(By.ID, "password") # 替换为实际定位符
login_button = driver.find_element(By.XPATH, "//button[@type='submit']") # 替换为实际定位符
# 输入凭据并提交
username_input.send_keys("your_username") # 替换为测试账号
password_input.send_keys("your_password") # 替换为测试密码
login_button.click()
# 验证登录成功 (等待跳转到主页或出现欢迎信息)
self.wait.until(
EC.presence_of_element_located((By.XPATH, "//h1[contains(text(), 'Dashboard')]"))
# 或者根据实际情况定位
)
print("登录成功!")
def navigate_to_product_management(self, driver):
"""导航到商品管理页面"""
print("导航到商品管理...")
# 示例:点击侧边栏的"商品管理"链接
product_mgmt_link = self.wait.until(
EC.element_to_be_clickable((By.LINK_TEXT, "商品管理")) # 替换为实际文本或定位符
)
product_mgmt_link.click()
# 可能需要等待页面加载
self.wait.until(
EC.presence_of_element_located((By.ID, "product-list-table")) # 替换为商品列表的定位符
)
def add_product(self, driver, name, price):
"""添加新商品"""
print(f"添加商品: {name}")
# 点击"添加商品"按钮
add_button = self.wait.until(
EC.element_to_be_clickable((By.ID, "add-product-btn")) # 替换为实际定位符
)
add_button.click()
# 等待模态框或新页面加载
name_input = self.wait.until(
EC.presence_of_element_located((By.ID, "product-name")) # 替换为实际定位符
)
price_input = driver.find_element(By.ID, "product-price") # 替换为实际定位符
save_button = driver.find_element(By.ID, "save-product-btn") # 替换为实际定位符
# 填写表单
name_input.send_keys(name)
price_input.send_keys(price)
# 保存
save_button.click()
# 等待保存成功提示或页面刷新
self.wait.until(
EC.invisibility_of_element_located((By.ID, "save-product-btn")) # 等待保存按钮消失(模态框关闭)
# 或者等待成功提示出现
)
print("商品添加成功!")
def verify_product_added(self, driver, product_name):
"""验证商品是否已添加到列表中"""
print("验证商品添加...")
# 在商品列表中查找新添加的商品
product_row = self.wait.until(
EC.presence_of_element_located((By.XPATH, f"//tr[td[contains(text(), '{product_name}')]]"))
)
self.assertIsNotNone(product_row, f"未能在列表中找到商品: {product_name}")
print("商品添加验证通过!")
def edit_product(self, driver, product_name, new_price):
"""编辑商品信息"""
print(f"编辑商品: {product_name}")
# 找到对应商品的"编辑"按钮
edit_button = self.wait.until(
EC.element_to_be_clickable((By.XPATH, f"//tr[td[contains(text(), '{product_name}')]]//button[@class='edit-btn']"))
# 根据实际HTML结构调整XPATH
)
edit_button.click()
# 等待编辑表单加载
price_input = self.wait.until(
EC.presence_of_element_located((By.ID, "edit-product-price")) # 替换为实际定位符
)
save_button = driver.find_element(By.ID, "update-product-btn") # 替换为实际定位符
# 清除旧价格并输入新价格
price_input.clear()
price_input.send_keys(new_price)
# 保存
save_button.click()
# 等待更新完成
self.wait.until(
EC.invisibility_of_element_located((By.ID, "update-product-btn"))
)
print("商品编辑成功!")
def verify_product_edited(self, driver, product_name, expected_price):
"""验证商品信息已更新"""
print("验证商品编辑...")
# 再次在列表中查找商品,检查价格是否更新
# 这里简化处理,实际可能需要刷新或重新查找
price_cell = self.wait.until(
EC.presence_of_element_located((By.XPATH, f"//tr[td[contains(text(), '{product_name}')]]/td[@class='price-column']"))
# 定位价格所在的单元格
)
actual_price = price_cell.text.strip()
self.assertEqual(actual_price, expected_price, f"商品价格未更新。期望: {expected_price}, 实际: {actual_price}")
print("商品编辑验证通过!")
def delete_product(self, driver, product_name):
"""删除商品"""
print(f"删除商品: {product_name}")
# 找到对应商品的"删除"按钮
delete_button = self.wait.until(
EC.element_to_be_clickable((By.XPATH, f"//tr[td[contains(text(), '{product_name}')]]//button[@class='delete-btn']"))
)
delete_button.click()
# 处理确认对话框 (通常为浏览器原生弹窗)
try:
alert = self.wait.until(EC.alert_is_present())
alert.accept() # 点击"确定"
print("确认删除")
except TimeoutException:
print("未检测到确认弹窗,继续...")
# 如果没有弹窗,可能需要点击模态框中的确认按钮
# confirm_delete_btn = driver.find_element(By.ID, "confirm-delete")
# confirm_delete_btn.click()
# 等待删除完成 (商品行消失或出现成功提示)
self.wait.until(
EC.invisibility_of_element_located((By.XPATH, f"//tr[td[contains(text(), '{product_name}')]]"))
)
print("商品删除成功!")
def verify_product_deleted(self, driver, product_name):
"""验证商品已从列表中删除"""
print("验证商品删除...")
# 尝试查找已删除的商品,应该找不到
with self.assertRaises(TimeoutException):
self.wait.until(
EC.presence_of_element_located((By.XPATH, f"//tr[td[contains(text(), '{product_name}')]]"))
)
print("商品删除验证通过!")
def tearDown(self):
"""测试后置操作:关闭浏览器"""
if self.driver:
self.driver.quit()
if __name__ == "__main__":
unittest.main(verbosity=2)
-
搜索功能类
import unittest
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
from selenium.webdriver.common.keys import Keys
import time
class TestSearchFunctionality(unittest.TestCase):
"""搜索功能自动化测试套件"""
def setUp(self):
"""初始化浏览器"""
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(10)
self.wait = WebDriverWait(self.driver, 10)
self.base_url = "https://your-website.com" # 替换为实际URL
def test_search_scenarios(self):
"""测试不同的搜索场景"""
driver = self.driver
driver.get(self.base_url)
# 确保搜索框存在
search_input = self.wait.until(
EC.presence_of_element_located((By.NAME, "q")) # 通常搜索框的name是'q'或'id'
# 或者 By.ID, By.CLASS_NAME 等
)
# 场景1: 正常搜索 (期望有结果)
self._test_normal_search(search_input, "laptop")
# 场景2: 空搜索 (期望有提示或保持原页面)
self._test_empty_search(search_input)
# 场景3: 无结果搜索 (期望显示"无结果"提示)
self._test_no_results_search(search_input, "xyz123abc")
# 场景4: 搜索建议 (如果支持)
self._test_search_suggestions(search_input, "lap")
def _test_normal_search(self, search_input, query):
"""测试正常搜索"""
print(f"执行正常搜索: '{query}'")
search_input.clear()
search_input.send_keys(query)
search_input.send_keys(Keys.RETURN) # 模拟回车
# 等待搜索结果页面加载
try:
results_container = self.wait.until(
EC.presence_of_element_located((By.ID, "search-results")) # 替换为实际结果容器ID
)
# 检查是否有结果 (至少一个结果项)
result_items = results_container.find_elements(By.CLASS_NAME, "result-item") # 替换为实际结果项类名
self.assertGreater(len(result_items), 0, f"搜索 '{query}' 未返回任何结果")
print(f"正常搜索成功,找到 {len(result_items)} 个结果")
except TimeoutException:
self.fail(f"搜索结果页面加载超时")
def _test_empty_search(self, search_input):
"""测试空搜索"""
print("执行空搜索")
search_input.clear()
search_input.send_keys(Keys.RETURN)
# 检查行为: 可能是显示提示信息,或者页面无变化
try:
# 情况A: 出现错误/提示信息
error_message = self.driver.find_element(By.CLASS_NAME, "search-error") # 替换为实际错误类名
self.assertIn("请输入", error_message.text, "空搜索的错误提示信息不正确")
print("空搜索 - 错误提示验证通过")
except NoSuchElementException:
# 情况B: 页面无变化 (仍在首页或原页面)
current_url = self.driver.current_url
# 检查URL是否未变或符合预期 (例如没有跳转到搜索结果页)
self.assertTrue(
self.base_url in current_url or "search" not in current_url.lower(),
"空搜索不应跳转到搜索结果页"
)
print("空搜索 - 页面未跳转验证通过")
def _test_no_results_search(self, search_input, query):
"""测试无结果搜索"""
print(f"执行无结果搜索: '{query}'")
search_input.clear()
search_input.send_keys(query)
search_input.send_keys(Keys.RETURN)
try:
# 等待搜索结果容器
results_container = self.wait.until(
EC.presence_of_element_located((By.ID, "search-results"))
)
# 检查是否显示"无结果"信息
no_results_element = results_container.find_element(By.CLASS_NAME, "no-results") # 替换为实际类名
self.assertIsNotNone(no_results_element, "未显示'无结果'提示")
self.assertIn("未找到", no_results_element.text, "无结果提示信息不正确")
print("无结果搜索验证通过")
except TimeoutException:
self.fail("搜索结果页面加载超时")
except NoSuchElementException:
# 检查结果列表是否为空
result_items = self.driver.find_elements(By.CLASS_NAME, "result-item")
self.assertEqual(len(result_items), 0, "无结果搜索返回了结果")
print("无结果搜索 - 结果为空验证通过")
def _test_search_suggestions(self, search_input, partial_query):
"""测试搜索建议 (自动补全)"""
print(f"测试搜索建议: 输入 '{partial_query}'")
search_input.clear()
search_input.send_keys(partial_query)
# 等待建议下拉框出现
try:
suggestions_dropdown = self.wait.until(
EC.visibility_of_element_located((By.CLASS_NAME, "suggestions-dropdown")) # 替换为实际类名
)
# 获取建议列表
suggestions = suggestions_dropdown.find_elements(By.CLASS_NAME, "suggestion-item") # 替换为实际类名
self.assertGreater(len(suggestions), 0, "搜索建议未出现")
# 检查第一个建议是否包含输入的部分
first_suggestion_text = suggestions[0].text.lower()
self.assertIn(partial_query.lower(), first_suggestion_text,
f"搜索建议 '{first_suggestion_text}' 不包含查询词 '{partial_query}'")
print(f"搜索建议测试通过,找到 {len(suggestions)} 个建议")
# 可选: 点击一个建议并验证跳转
# suggestions[0].click()
# self.wait.until(EC.url_changes(self.driver.current_url))
# print("点击建议并跳转成功")
except TimeoutException:
print("搜索建议未在预期时间内出现 (可能功能未启用或加载慢)")
def tearDown(self):
"""关闭浏览器"""
if self.driver:
self.driver.quit()
if __name__ == "__main__":
unittest.main(verbosity=2)
页面元素与布局检查
import unittest
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
class TestPageElements(unittest.TestCase):
"""页面元素与布局检查测试套件"""
def setUp(self):
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(10)
self.wait = WebDriverWait(self.driver, 10)
self.base_url = "https://your-website.com"
def test_homepage_elements(self):
"""测试主页关键元素"""
driver = self.driver
driver.get(self.base_url)
# 1. 验证页面标题
expected_title = "Your Website Title"
self.assertEqual(driver.title, expected_title, f"页面标题不匹配。期望: {expected_title}, 实际: {driver.title}")
# 2. 验证Logo存在且可见
logo = self.wait.until(
EC.visibility_of_element_located((By.ID, "logo")) # 或 By.CLASS_NAME, By.CSS_SELECTOR
)
self.assertTrue(logo.is_displayed(), "Logo未显示")
self.assertTrue(logo.size['height'] > 0 and logo.size['width'] > 0, "Logo尺寸为0")
# 3. 验证主导航菜单
nav_menu = self.wait.until(
EC.presence_of_element_located((By.ID, "main-nav"))
)
self.assertTrue(nav_menu.is_displayed(), "主导航菜单未显示")
# 检查关键导航链接
expected_links = ["首页", "产品", "关于我们", "联系我们"]
for link_text in expected_links:
try:
nav_link = driver.find_element(By.LINK_TEXT, link_text)
self.assertTrue(nav_link.is_displayed(), f"导航链接 '{link_text}' 未显示")
self.assertTrue(nav_link.get_attribute("href"), f"导航链接 '{link_text}' 缺少 href")
except NoSuchElementException:
self.fail(f"未找到导航链接: {link_text}")
# 4. 验证搜索框
search_input = driver.find_element(By.NAME, "q")
self.assertTrue(search_input.is_displayed(), "搜索框未显示")
self.assertEqual(search_input.get_attribute("placeholder"), "搜索...", "搜索框占位符不正确")
# 5. 验证页脚信息
footer = self.wait.until(
EC.presence_of_element_located((By.TAG_NAME, "footer"))
)
self.assertTrue(footer.is_displayed(), "页脚未显示")
# 检查版权信息
copyright_text = footer.find_element(By.CLASS_NAME, "copyright").text
self.assertIn("©", copyright_text, "页脚版权信息缺少 © 符号")
current_year = str(time.localtime().tm_year)
self.assertIn(current_year, copyright_text, f"页脚版权年份应包含 {current_year}")
# 6. 验证关键内容区域 (例如轮播图)
try:
carousel = driver.find_element(By.ID, "hero-carousel")
self.assertTrue(carousel.is_displayed(), "首页轮播图未显示")
except NoSuchElementException:
print("首页轮播图元素未找到,跳过检查")
def tearDown(self):
if self.driver:
self.driver.quit()
if __name__ == "__main__":
unittest.main(verbosity=2)
-
案例展示
Web自动化知识
一、考前准备
Pip install pytest
Pip install selenium
Pip install selenium.webdriver.(显示等待)
生成 requirements.txt 文件
安装好所有依赖包后,可以使用以下命令生成 requirements.txt 文件。
pip freeze >requirements.txt
这条命令会将当前虚拟环境中的所有已安装包及其版本信息输出到requirements.txt 文件中。
使用 requirements.txt 文件安装依赖
在新的环境或其他开发人员的机器上,可以使用requirements.txt 文件来安装项目的所有依赖包。
首先,确保激活虚拟环境,然后运行以下命令:
pip install -r requirements.txt
这条命令会读取 requirements.txt 文件并安装其中列出的所有依赖包。
环境搭建
#导包
#指定驱动服务更快速
import time
from selenium import webdriver
#创建浏览器对象
driver=webdriver.Chrome()
# 打开商品管理页面
driver.get("https://litemall.hogwarts.ceshiren.com/")
#页面最大化
driver.maximize_window()
time.sleep(5)
#关闭驱动
driver.quit()
二、元素定位及找不到怎么办
元素定位
name
driver.find_element(By.NAME,"password").clear()
id
driver.find_element(By.ID,"password")
LINK_TEXT(找不到元素试试直接中文)
driver.find_element(By.LINK_TEXT, "通讯录").click()
tag name
xpath
1.有明确文本的:driver.find_element(By.XPATH,"//*[text()='商品列表']")
2.输入框输入"//label[text()='商品编号']/following-sibling::div//input"
利用页面结构(label + 输入框)进行相对定位,非常稳定,适合表单输入
3.包含文本匹配://*[contains(text(), '商品')]
用途:查找文本中包含“商品”的任意元素。
4.部分匹配
✅ XPath 中的部分匹配函数
匹配类型 CSS Selector XPath
以...开头 [attr^='value'] starts-with(@attr, 'value')
以...结尾 [attr$='value'] ends-with(@attr, 'value')
包含... [attr*='value'] contains(@attr, 'value')
css_selector
id,#开头
class,.开头
部分匹配
self.driver.find_element(By.CSS_SELECTOR, "input[id^='user']") # id 以 user 开头 self.driver.find_element(By.CSS_SELECTOR, "input[id$='Name']") # id 以 Name 结尾# self.driver.find_element(By.CSS_SELECTOR, "input[class*='input']") # class 包含 input
calss_name(多个名选取其中一个)
PARTIAL_LINK_TEXT = "partial link text"
页面没有加载完成
显示等待
#下载 pip install selenium.webdriver.
#导入包
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
el = WebDriverWait(driver, 5).until(EC.presence_of_element_located((By.XPATH, '//* [@id="1"]/div/h3/a'))) # driver.find_element(By.XPATH, '//*[@id="1"]/div/h3/a').click() el.click()
隐式等待
driver.implicitly_wait(3)
强制等待
impot time Time.sleep()
框架内元素不可找
当元素在子页面的frame元素中需要进行切换定位
driver.switch_to.frame(driver.find_element(By.XPATH, '/html/frameset/frame[1]'))
//大框架frame的定位
driver.find_element(By.XPATH, '//*[@id="navs"]/ul/li[2]/a').//click()真正元素定位
元素变化
//*[@id="auto-id-ri6QaGIEhN3bTxsA"]
//*[@id="auto-id-ghlNbd98dkqJFidB"]
//*[@id="auto-id-4SCakBx15gzHDRud"]
# 定位以 auto-id- 开头的 id 元素
element = driver.find_element(By.XPATH, '//*[starts-with(@id, "auto-id-")]')
成功://*[@id="fanwe_success_box"]/table/tbody/tr/td[2]/div[2]
失败://*[@id="fanwe_error_box"]/table/tbody/tr/td[2]/div[2]
# 不管是正例和反例的提示信息都要进行获取
# 可以通过手写xpath以**开头进行定位
text = driver.find_element(By.XPATH, '//*[starts-
with(@id,"fanwe_")]/table/tbody/tr/td[2]/div[2]').text
//把变化的去掉留下固定的就好
转换路径法
当搜索按钮实在定位不到,可以用回车键替代
from selenium.webdriver.common.keys import Keys# 输入完直接按回车 = 搜索search_input = self.driver.find_element(By.CSS_SELECTOR,
'[placeholder="搜索"]')
search_input.send_keys(search_key)
search_input.send_keys(Keys.ENTER) # 回车触发搜索
三、断言知识
✅ 五、常见断言方法总结(Python)
断言方法 说明
assert x == y 相等
assert x in y 包含
assert x.startswith(y) 以...开头
assert elem.is_displayed() 元素可见
assert elem.is_enabled() 元素可操作
self.assertEqual(a, b) unittest 相等断言
self.assertIn(a, b) unittest 包含断言
self.assertTrue(expr) 表达式为真
列子:
assert "登录成功" in message, f"期望包含'登录成功',实际是:{message}"
6. 元素存
在性断言
检查某个元素是否存在(注意:不存在会抛异常)。
from selenium.common.exceptions
import NoSuchElementExceptiontry:
driver.find_element(By.ID, "logout-btn")
assert True # 找到了
except NoSuchElementException:
assert False, "未找到退出按钮"
4. 元素状态断言
检查元素是否可见、可点击、被选中等。
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
elem = driver.find_element(By.ID, "submit-btn")
# 是否可见
assert elem.is_displayed()
# 是否可点击
assert elem.is_enabled()
# 是否被选中(如复选框)
assert elem.is_selected()
# 使用 expected_conditions 做显式等待 + 断言
wait = WebDriverWait(driver, 10)
wait.until(EC.element_to_be_clickable((By.ID, "submit-btn")))
四、不同应用题模版
1.商品管理类
2.搜索功能类
五、案例展示
import time
import pytest
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class Test:
def setup_method(self):
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(10)
# =======打开测试人论坛========
self.driver.get("https://ceshiren.com/")
self.driver.maximize_window()
def teardown_method(self):
# driver 退出
self.driver.quit()
def close_msg(self):
# 处理可能出现的弹窗
if "确定" in self.driver.page_source:
self.driver.find_element(By.XPATH, '//*[text()="确定"]').click()
# parametrize 只能在test_ python文件中的test_开头的方法上使用
# 正向用例
@pytest.mark.parametrize(
"search_key",
[
"pytest",
"面试题",
"a",
"appium desktop连接真机,start session,出现报错,手机上appium setting打开闪退,但是进程显示是进行中。报错内容:An unknown server-side error occurred while processing the command. Original error: Could not find a connected Android device in 20364ms.",
]
)
def test_search(self, search_key):
# =============== 2. 点击搜索按钮 ==============
self.driver.find_element(By.XPATH, '//*[@id="search-button"]').click()
# =============== 3. 输入搜索关键字 ==============
ele_send = self.driver.find_element(By.ID, 'search-term')
ele_send.clear()
ele_send.send_keys(search_key)
# =============== 4. 点击进入高级搜索页面 ==============
ele = WebDriverWait(self.driver, 10).until(
EC.visibility_of_element_located((By.CLASS_NAME, 'd-icon-sliders-h'))
)
ele.click()
# 等待搜索结果链接可点击
search_ele = WebDriverWait(self.driver, 5).until(
EC.element_to_be_clickable((By.CLASS_NAME, "search-link"))
)
# ✅ 关键修复:滚动到元素可见位置解决长文本测试失败问题
self.driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", search_ele)
# 可选:加个小延迟
time.sleep(0.3)
# 获取文本
search_text = search_ele.text
print(f"高级搜索页面下第一个标题的文本为:{search_text}")
self.close_msg() # 处理弹窗
# --------------- 5. 点击标题 ---------------
search_ele.click() # 现在应该可以点击了
# 显式等待跳转后页面加载
WebDriverWait(self.driver, 5).until(
EC.visibility_of_element_located((By.XPATH, '//*[@class="fancy-title"]'))
)
# 断言
result_page_title = self.driver.title
print(f"跳转页面的标题为:{result_page_title}")
assert search_text in result_page_title
# 为空
def test_search_none(self):
# =============== 2. 点击搜索按钮 ==============
self.driver.find_element(By.XPATH, '//*[@id="search-button"]').click()
# =============== 3. 输入搜索关键字 ==============
ele_send = self.driver.find_element(By.ID, 'search-term')
ele_send.clear()
ele_send.send_keys("")
# 处理可能出现的弹窗
self.close_msg()
# =============== 4. 点击进入高级搜索页面 ==============
ele = WebDriverWait(self.driver, 10).until(
EC.visibility_of_element_located((By.CLASS_NAME, 'd-icon-sliders-h'))
)
ele.click()
# 点击搜索按钮
self.driver.find_element(By.CSS_SELECTOR, ".search-cta").click()
# 获取为空搜索时的提示信息
msg = self.driver.find_element(By.XPATH, "//*[@class='fps-invalid']").text
print(f"提示信息为:{msg}")
# 断言
assert msg == "您的搜索词过短。"
# 无搜索结果
def test_search_no_result(self):
# =============== 2. 点击搜索按钮 ==============
self.driver.find_element(By.XPATH, '//*[@id="search-button"]').click()
# =============== 3. 输入搜索关键字 ==============
ele_send = self.driver.find_element(By.ID, 'search-term')
ele_send.clear()
ele_send.send_keys("1234567890") # 输入一个不可能存在的关键词
# 处理可能出现的弹窗
self.close_msg()
# =============== 4. 点击进入高级搜索页面 ==============
ele = WebDriverWait(self.driver, 10).until(
EC.visibility_of_element_located((By.CLASS_NAME, 'd-icon-sliders-h'))
)
ele.click()
# 点击搜索按钮
self.driver.find_element(By.CSS_SELECTOR, ".search-cta").click()
# 获取无搜索结果时的提示信息
msg = self.driver.find_element(By.CSS_SELECTOR, ".loading-container > h3").text
print(f"提示信息为:{msg}")
# 断言
assert msg == "没有找到更多结果。"
更多推荐


所有评论(0)