高级定位-css
- css 选择器有自己的语法规则和表达式
- css 定位通常分为绝对定位和相对定位
- 和Xpath一起常用于UI自动化测试中的元素定位
css 相对定位的优点
- 可维护性更强
- 语法更加简洁
- 解决各种复杂的定位场景
# 绝对定位
$("#ember63 > td.main-link.clearfix.topic-list-data > span > span > a")
# 相对定位
$("#ember63 [title='新话题']")
css 定位的调试方法
- 进入浏览器的console
- 输入:
$("css表达式")
- 或者
$("css表达式")
css基础语法
//在console中的写法
// https://www.baidu.com/
//标签名
$('input')
//.类属性值
$('.s_ipt')
//#id属性值
$('#kw')
//[属性名='属性值']
$('[name="wd"]')
css关系定位
//在console中的写法
//元素,元素
$('.bg,.s_ipt_wr,.new-pmd,.quickdelete-wrap')
//元素>元素
$('#s_kw_wrap>input')
//元素 元素
$('#form input')
//元素+元素,了解即可
$('.soutu-btn+input')
//元素1~元素2,了解即可
$('.soutu-btn~i')
css 顺序关系
//:nth-child(n)
$('#form>input:nth-child(2)')
//:nth-of-type(n)
$('#form>input:nth-of-type(1)')
高级定位-xpath
xpath基本概念
- XPath 是一门在 XML 文档中查找信息的语言
- XPath 使用路径表达式在 XML 文档中进行导航
- XPath 的应用非常广泛
- XPath 可以应用在UI自动化测试
xpath 相对定位的优点
- 可维护性更强
- 语法更加简洁
- 相比于css可以支持更多的方式
# 复制的绝对定位
$x('//*[@id="ember75"]/td[1]/span/a')
# 编写的相对行为
$x("//*[text()='技术分享 | SeleniumIDE用例录制']")
xpath 定位的调试方法
* 浏览器-console
* `$x("xpath表达式")`
* 浏览器-elements
* ctrl+f 输入xpath或者css
xpath基础语法
# 整个页面
$x("/")
# 页面中的所有的子元素
$x("/*")
# 整个页面中的所有元素
$x("//*")
# 查找页面上面所有的div标签节点
$x("//div")
# 查找id属性为site-logo的节点
$x('//*[@id="site-logo"]')
# 查找节点的父节点
$x('//*[@id="site-logo"]/..')
xpath 顺序关系
# 获取此节点下的所有的li元素
$x("//*[@id='ember21']//li")
# 获取此节点下【所有的节点的】第一个li元素
$x("//*[@id='ember21']//li[1]")
xpath 高级用法
-
[last()]
: 选取最后一个 -
[@属性名='属性值' and @属性名='属性值']
: 与关系 -
[@属性名='属性值' or @属性名='属性值']
: 或关系 -
[text()='文本信息']
: 根据文本信息定位 -
[contains(text(),'文本信息')]
: 根据文本信息包含定位 - 注意:所有的表达式需要和
[]
结合
# 选取最后一个input标签
//input[last()]
# 选取属性name的值为passward并且属性pwd的值为123456的input标签
//input[@name='passward' and @pwd='123456']
# 选取属性name的值为passward或属性pwd的值为123456的input标签
//input[@name='passward' or @pwd='123456']
# 选取所有文本信息为'霍格沃兹测试开发'的元素
//*[text()='霍格沃兹测试开发']
# 选取所有文本信息包'霍格沃兹'的元素
//*[contains(text(),'霍格沃兹')]
显示等待高级使用
显示等待原理
- 在代码中定义等待一定条件发生后再进一步执行代码
- 在最长等待时间内循环执行结束条件的函数
- WebDriverWait(driver 实例, 最长等待时间, 轮询时间).until(结束条件函数)
显示等待-封装等待条件
- 官方的 excepted_conditions 不可能覆盖所有场景
- 定制封装条件会更加灵活、可控
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.support.wait import WebDriverWait
class TestWebdriverWait:
driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(5)
driver.get("https://vip.ceshiren.com/#/ui_study")
def teardown(self):
self.driver.quit()
def test_webdriver_wait(self):
# 解决的问题:有的按钮点击一次没有反应,可能要点击多次,比如企业微信的添加成员
# 解决的方案:一直点击按钮,直到下个页面出现,封装成显式等待的一个条件
def muliti_click(button_element,until_ele):
# 函数封装
def inner(driver):
# 封装点击方法
driver.find_element(By.XPATH,button_element).click()
return driver.find_element(By.XPATH,until_ele)
return inner
time.sleep(5)
# 在限制时间内会一直点击按钮,直到展示弹框
WebDriverWait(self.driver,10).until(muliti_click("//*[text()='点击两次响应']","//*[text()='该弹框点击两次后才会弹出']"))
time.sleep(5)
高级控件交互方法
ActionChains解析
- 实例化类ActionChains,参数为driver实例。
- 中间可以有多个操作。
-
.perform()
代表确定执行。
ActionChains(self.driver).操作.perform()
键盘事件-使用shift实现大写
-
ActionChains(self.driver)
: 实例化ActionChains类 -
key_down(Keys.SHIFT, ele)
: 按下shift键实现大写 -
send_keys("selenium")
: 输入大写的selenium -
perform()
: 确认执行
键盘事件-输入后回车
- 直接输入回车: 元素.send_keys(Keys.ENTER)
- 使用ActionChains: key_down(Keys.ENTER)
class TestKeyBoardDemo:
def setup_class(self):
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(3)
def teardown_class(self):
self.driver.quit()
def test_enter(self):
# 演练环境
self.driver.get("https://www.sogou.com/")
ele = self.driver.find_element(By.ID, "query")
ele.send_keys("selenium")
# 第一种方式
ele.send_keys(Keys.ENTER)
# 第二种方式
# ActionChains(self.driver).\
# key_down(Keys.ENTER).\
# perform()
time.sleep(3)
键盘事件-复制粘贴
- 多系统兼容
- mac 的复制按钮为 COMMAND
- windows 的复制按钮为 CONTROL
- 左箭头:
Keys.ARROW_LEFT
- 按下COMMAND或者CONTROL:
key_down(cmd_ctrl)
- 按下剪切与粘贴按钮:
send_keys("xvvvvv")
鼠标事件
- 双击
-
double_click(元素对象)
: 双击元素
class TestMouseDemo:
def setup_class(self):
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(3)
def teardown_class(self):
self.driver.quit()
def test_double_click(self):
# 演练环境
self.driver.get("https://vip.ceshiren.com/#/ui_study")
ele = self.driver.find_element(By.ID, "primary_btn")
ActionChains(self.driver).double_click(ele).perform()
time.sleep(2)
- 拖动元素
-
drag_and_drop(起始元素对象, 结束元素对象)
: 拖动并放开元素
class TestMouseDemo:
def setup_class(self):
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(3)
def teardown_class(self):
self.driver.quit()
def test_drag_and_drop(self):
# 演练环境
self.driver.get("https://vip.ceshiren.com/#/ui_study/action_chains")
item_left = self.driver.find_element(By.CSS_SELECTOR,'#item1')
item_right = self.driver.find_element(By.CSS_SELECTOR,'#item3')
ActionChains(self.driver).drag_and_drop(item_left, item_right).perform()
time.sleep(5)
- 指定位置(悬浮)
-
move_to_element(元素对象)
: 移动到某个元素
class TestMouseDemo:
def setup_class(self):
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(3)
def teardown_class(self):
self.driver.quit()
def test_hover(self):
# 演练环境
self.driver.get("https://vip.ceshiren.com/#/ui_study/action_chains2")
time.sleep(2)
title = self.driver.find_element(By.CSS_SELECTOR, '.title')
ActionChains(self.driver).move_to_element(title).perform()
options = self.driver.find_element(By.CSS_SELECTOR,'.options>div:nth-child(1)')
ActionChains(self.driver).click(options).perform()
time.sleep(5)
滚轮/滚动操作
- 滚动到元素
-
scroll_to_element(WebElement对象)
:滚动到某个元素
class TestScrollDemo:
def setup_class(self):
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(3)
def teardown_class(self):
self.driver.quit()
def test_scoll_to_element(self):
# 演练环境
self.driver.get("https://ceshiren.com/")
# 4.2 之后才提供这个方法
ele = self.driver.find_element\
(By.XPATH, "//*[text()='怎么写高可用集群部署的测试方案?']")
ActionChains(self.driver).scroll_to_element(ele).perform()
time.sleep(5)
- 根据坐标滚动
scroll_by_amount(横坐标, 纵坐标)
class TestScrollDemo:
def setup_class(self):
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(3)
def teardown_class(self):
self.driver.quit()
def test_scroll_to_amount(self):
# 演练环境
self.driver.get("https://ceshiren.com/")
# 4.2 之后才提供这个方法
ActionChains(self.driver).scroll_by_amount(0, 10000).perform()
time.sleep(5)
自动化关键数据记录
什么是关键数据
- 代码的执行日志
- 代码执行的截图
- page source(页面源代码)
行为日志记录
- 日志配置
- 脚本日志级别
- debug记录步骤信息
- info记录关键信息,比如断言等
# 日志配置
import logging
# 创建logger实例
logger = logging.getLogger('simple_example')
# 设置日志级别
logger.setLevel(logging.DEBUG)
# 流处理器
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
# 日志打印格式
formatter = logging.Formatter\
('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# 添加格式配置
ch.setFormatter(formatter)
# 添加日志配置
logger.addHandler(ch)
步骤截图记录
save_screenshot(截图路径+名称)
- 记录关键页面
- 断言页面
- 重要的业务场景页面
- 容易出错的页面
# 调用save方法截图并保存保存在当前路径下的images文件夹下
driver.save_screenshot('./images/search1.png')
page_source记录
- 使用page_source属性获取页面源码
- 在调试过程中,如果有找不到元素的错误可以保存当时的page_source调试代码
# 在报错行前面添加保存page_source的操作
with open("record.html", "w", encoding="u8") as f:
f.write(self.driver.page_source)