【web自动化测试】
安装selenium库
eg.
安装指定版本(4.2)的库
pip install selenium==4.2
初级:
selenium常见方法的基本使用
基本web自动化测试用例编写
中级:
web自动化测试技巧进阶使用(显示等待、隐式等待)
用例集成截图、日志、报告
高级:
PageOject设计模式
基于pageobject模式的测试用例的编写
资深与拓展:
初级:
形式 | 章节 | 描述 |
---|---|---|
知识点 | Web 自动化测试价值与体系 | 价值体系 技术选型 学习路线 |
知识点 | 环境安装与使用 | selenium、 chromedriver、 firefox geckodriver |
知识点 | 自动化用例录制 | selenium IDE、录制、回放、基本使用 |
知识点 | 自动化测试用例结构分析 | 录制代码解析,代码结构优化 |
知识点 | web 浏览器控制 | 打开网页、刷新、回退、最大化、最小化 |
知识点 | 常见控件定位方法 | id name css xpath link 定位 |
知识点 | 强制等待与隐式等待 | 介绍 selenium 经典的三种等待方式 |
知识点 | 常见控件交互方法 | 点击,输入,清空,获取元素文本、尺寸等属性信息 |
实战 | 测试人论坛搜索功能自动化测试 | 用例设计、用例编写、断言 |
中级:
形式 | 章节 | 描述 |
---|---|---|
知识点 | 高级定位-css | css 使用场景、语法 |
知识点 | 高级定位-xpath | xpath 使用场景、语法 |
知识点 | 显式等待高级使用 | 显式等待原理与使用 |
知识点 | 高级控件交互方法 | 右键点击、页面滑动、表单填写等自动化动作 |
知识点 | 网页 frame 与多窗口处理 | 多窗口,多 frame 下的窗口识别与切换 |
知识点 | 文件上传弹框处理 | 文件上传的自动化与弹框处理机制 |
知识点 | 自动化关键数据记录 | 行为日志、截图,page source |
实战 | 电子商务产品实战 | 用例设计、日志封装、测试报告 |
训练营 | 知名产品web自动化测试实战 | 用例设计、日志封装、测试报告 |
高级:
形式 | 章节 | 描述 |
---|---|---|
知识点 | 浏览器复用 | 利用远程调试技术实现自动化登录 |
知识点 | Cookie 复用 | 利用 cookie 复用实现自动化登录 |
知识点 | page object 设计模式 page object 模式的发展历史介绍、六大设计原则 | |
知识点 | 异常自动截图 | 测试用例失败时自动截图 |
知识点 | 测试用例流程设计 | 测试装置的应用,套件级别的初始化与清理、用例级别的初始化与清理 |
实战 | 电子商务产品实战 page object 设计模式应用、BasePage 封装、基于 page object 模式的测试用例编写 | |
训练营 | web自动化测试进阶实战 | page object 设计模式应用、BasePage 封装、基于 page object 模式的测试用例编写 |
资深:
形式 | 章节 | 描述 |
---|---|---|
知识点 | selenium 多浏览器处理 | chrome、firefox 等浏览器的自动化支持 |
知识点 | 执行 javascript 脚本 | 使用 selenium 直接在当前页面中进行 js 交互 |
知识点 | selenium option 常用操作 | selenium option 的介绍与使用 |
知识点 | capability 配置参数解析 | capability 用法 ,firefox chrome 等浏览器的专属 capability |
知识点 | cypress 测试框架介绍 | web 自动化测试框架 cypress |
SeleniumIDE其实是浏览器上的一个插件。
官网:https://www.selenium.dev/
Chrome插件:https://chrome.google.com/webstore/detail/selenium-ide/mooikfkahbdckldjjndioackbalphokd
Firefox插件:https://addons.mozilla.org/en-US/firefox/addon/selenium-ide/
SeleniumIDE
用例录制、用例集、导出脚本
打开网页、刷新、回退、最大化、最小化、强制等待
from selenium import webdriver
import time
driver = webdriver.Firefox()
driver.get("https://www.baidu.com/") #打开百度
#driver.minimize_window() #页面最小化
driver.maximize_window() #页面最小化
time.sleep(2) #强制等待2秒
driver.refresh() #刷新浏览器,refresh是方法,所以要加括号
driver.get("https://blog.csdn.net/") #打开CSDN
driver.back() #退回上一步,即退回百度
sleep(1)
(1)html
DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>测试人论坛title>
head>
<body>
<a href="https://ceshiren.com/" class="link">链接a>
body>
html>
(2)八大定位方式
https://www.selenium.dev/documentation/webdriver/elements/locators/
练习网站
https://vip.ceshiren.com/#/ui_study/
方式 | 描述 |
---|---|
class name | class 属性对应的值 |
css selector(重点) | css 表达式 |
id(重点) | id 属性对应的值\ |
name(重点) | name 属性对应的值 |
link text | 查找其可见文本与搜索值匹配的锚元素 |
partial link text | 查找其可见文本包含搜索值的锚元素。如果多个元素匹配,则只会选择第一个元素。 |
tag name | 标签名称 |
xpath(重点) | xpath表达式 |
1)元素定位方式一:ID
#格式1,举例
driver.find_element_by_id("su")
#格式2,举例,建议使用格式2
driver.find_element(By.ID,"su")
eg.
from selenium import webdriver
import time
from selenium.webdriver.common.by import By
def id_position_method():
# 实例化chromedriver
driver = webdriver.Chrome()
# 打开网站
driver.get('http://www.ceshiren.com')
# 等待一秒
time.sleep(1)
# 点击“精华帖”
driver.find_element(By.ID,"ember35").click()
# 等待两秒
time.sleep(2)
if __name__ == '__main__':
id_position_method()
2)元素定位方式二:name
driver.find_element(By.NAME,"Name属性对应的值“)
3)元素定位方式三:css selector (必须掌握)
driver.find_element(By.CSS_SELECTOR, "值")
#方式一:
#页面右击,复制绝对定位
#方式二:
#编写css selector表达式(必须会)
4)元素定位方式四:xpath (必须掌握)
#格式
driver.find_element(By.XPATH, "值")
#方式一:
#页面右击,复制绝对定位
#方式二:
#编写xpath表达式(必须会)
5)元素定位方式五:链接文本
A、一定是a标签
B、输入的元素为标签内的文本
driver.find_element(By.LINK_TEXT, "a标签内的文本")
(1)强制等待(不确定到底需要等待多长时间,sleep时间过长会影响用例执行效率,sleep时间过短,会报错。不能解决不稳定性的问题)
eg.
time.sleep(3)
(2)隐式等待 (解决找不到元素的问题。因强制等待时间过短,页面未加载完成就点击元素,报no such element的错误的问题)
eg.
driver.implicity_wait(3) #每0.5s轮询查找元素是否出现,如果没出现就抛出异常
(3)显示等待(解决元素可以找到,但点击效果没有触发的问题。解决点击等交互性场景下的等待问题。)
eg.
WebDriverWait(driver, 10).util(exoexted_conditions.element_to_be_clickable((By.ID, "success_btn"))) #10是等待时长
driver.find_element(By.ID, "success_btn").click()
(1)点击
driver.find_element(By.ID, "kw").click()
(2)输入
driver.find_element(By.ID, "kw").send_keys("百度")
(3)清空搜索框中的信息
driver.find_element(By.ID, "kw").clear()
(4)获取元素文本
driver.find_element(By.ID, "id").text
(5)获取元素的属性(html的属性值)
driver.find_element(By.ID, "id").get_attribute("name")
Web弹窗定位
场景1、web页面alert弹窗
解决1、driver.switchTo().alert()
下拉框、日期控件定位
场景2、
标签组合的下拉框无法定位
标签组合的日期控件无法定位
解决2、引入JS注入技术
文件上传
场景3、input标签文件上传
解决3、input标签直接使用send_keys()方法
driver.find_element(By.CSS_SELECTOR, "值")
#方式一:
#页面右击,复制绝对定位
#方式二:
#编写css selector表达式(必须会)
(1)定位场景
支持web产品
支持app端的webview
(2)绝对定位
右击—>复制—>css表达式
eg.
$("#ember63 > td.main-link.clearfix.topic-list-data > span > span > a")
缺点:层级关系过于明确,当从中抽掉一层span,就会定位不到元素。即无法适应前端页面的变化
(3)相对定位
优势:可维护性强、语法简单、解决各种复杂场景
$("#ember63 [title='新话题']")
#先找id为ember63的位置,在在其下找titile为新话题的元素
若$(“css表达式”)的方式不行,可以试试输入 $$(“css表达式”)。(可能是浏览器的原因)
(4)css基础语法
#标签名
$('input')
#.类属性值 #如果class后的值中含空格,则css表达式中空格要换成点.
$('.s_ipt')
#id属性值
$('#kw')
#[属性名='属性值']
$('[name="wd"]')
注:
批量修改pycharm中的变量,选中——右击——点击refactor——点击rename
driver->self.driver,实现跨方法使用变量
(5)css关系定位
类型 | 格式 |
---|---|
后代 | 元素 元素 |
父子 | 元素>元素 |
并集 | 元素,元素 |
邻近兄弟(了解即可) | 元素+元素 |
兄弟(了解即可) | 元素1~元素2 |
(6)css顺序关系
类型 | 格式 |
---|---|
父子关系+顺序 | 元素 元素 |
父子关系+标签类型+顺序 | 元素 元素 |
eg.
#:nth-child(n)
$('#form>input:nth-child(2)')
#:nth-of-type(n)
$('#form>input:nth-of-type(1)')
(1)定位场景
web自动化测试
app自动化测试
(2)优势
可维护性强、语法简洁、相比于css可以支持更多的方式
(3)调试方法
console
$x("xpath表达式")
elements
#ctrl+f输入xpath或者css
(4)xpath基础语法
表达式 | 结果 |
---|---|
/ | 从该节点的子元素选取 |
// | 从该节点的子孙元素选取 |
* | 通配符 |
nodename | 选取此节点的所有子节点 |
… | 选取当前节点的父节点 |
@ | 选取属性 |
eg.
# 整个页面
$x("/")
# 页面中的所有的子元素
$x("/*")
# 整个页面中的所有元素
$x("//*")
# 查找页面上面所有的div标签节点
$x("//div")
# 查找id属性为site-logo的节点
$x('//*[@id="site-logo"]')
# 查找节点的父节点
$x('//*[@id="site-logo"]/..')
(5)xpath顺序关系(索引)
xpath通过索引值直接获取对应元素
# 获取此节点下的所有的li元素
$x("//*[@id='ember21']//li")
# 获取此节点下【所有的节点的】第一个li元素
$x("//*[@id='ember21']//li[1]")
(6)xpath高级用法
[last()]: 选取最后一个
[@属性名=‘属性值’ and @属性名=‘属性值’]: 与关系
[@属性名=‘属性值’ or @属性名=‘属性值’]: 或关系
[text()=‘文本信息’]: 根据文本信息定位
[contains(text(),‘文本信息’)]: 根据文本信息包含定位
注意:所有的表达式需要和[]结合
eg.
# 选取最后一个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(),'霍格沃兹')]
键盘输入
eg1.
键盘按下回车
#法一:
self.driver.find_element(By.ID, "query").send_keys(Keys.ENTER)
#法二:
ActionChains(self.driver).key_down(Keys.ENTER).perform()
eg2
键盘复制粘贴
class TestKeyBoardDemo:
# driver 初始化
def setup_class(self):
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(3)
# 关闭driver进程
def teardown_class(self):
self.driver.quit()
# 复制粘贴逻辑
def test_copy_and_paste(self):
# 演练环境
self.driver.get("https://ceshiren.com/")
cmd_ctrl = Keys.COMMAND if sys.platform == 'darwin' else Keys.CONTROL
self.driver.find_element(By.ID, "search-button").click()
ele = self.driver.find_element(By.ID, "search-term")
# 打开搜索,选择搜索框,输入selenium,剪切后复制,几个v就代表复制几次
ActionChains(self.driver)\
.key_down(Keys.SHIFT, ele)\
.send_keys("Selenium!")\
.send_keys(Keys.ARROW_LEFT)\
.key_down(cmd_ctrl)\
.send_keys("xvvvvv")\
.key_up(cmd_ctrl)\
.perform()
time.sleep(5)
鼠标事件
eg1.
双击
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)
eg2.
拖动元素
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)
eg3.
悬浮
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)
滚轮滚动
使用条件:
1、仅使用selenium版本>=4.2
2、适用Chrome,不适用于Firefox
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)
滚轮根据坐标滚动
eg.
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)
eg.
from time import sleep
from selenium import webdriver
from selenium.webdriver.common.by import By
class TestFile:
def setup(self):
#添加无头模式后,运行代码,可以不直接打开浏览器。这样你可以边执行代码边办公
options = webdriver.FirefoxOptions() #无头模式代码
options.add_argument('--headless') #无头模式代码
#options.add_argument('start-maximized')
#options.add_argument('window-size=1920x3000')
self.driver = webdriver.Firefox(options=options) #无头模式代码
self.driver.implicitly_wait(3)
# self.driver.maximize_window()
def teardown(self):
self.driver.quit()
def test_file(self):
self.driver.get("http://www.baidu.com")
self.driver.find_element(By.CSS_SELECTOR, ".soutu-btn").click()
sleep(2)
# self.driver.find_element(By.CSS_SELECTOR, ".upload-pic").send_keys('C:\\Users\\mayr_\\Desktop\\aaaaaaaaaa\\1.png')
# sleep(20)