自动化测试理论
-
UI:User Interface(用户接口-用户界面),主要包括:app、web
-
ui自动化测试:使用工具或代码执行用例的过程
-
什么样的项目适合做自动化
1、需要回归测试项目(甲方自营项目、金融、电商) 2、需求变动不频繁:稳定的模块 3、项目周期长的项目:(甲方自营项目、6个月以上的外包项目)
-
自动化测试的目的:提高测试效率
自动化测试工具及环境
工具说明
- 工具
- QTP:商业、收费、支持UI
- robot Framework:python扩展库、使用封装好的关键字驱动、半代码水平、支持UI
- selenium:开源、免费、主流 支持UI
- selenium介绍
提示:1、selenium-grid可以做分布式(批量在不同平台中运行用例),自动化用例较多时、或测试不同浏览器在不同平台运行时可以使用。2、对页面元素实施自动化测试,主要使用:webdriver
环境搭建
-
所需环境:python 解释器+pycharm+selenium+浏览器+浏览器驱动
-
selenium
pip install selenium
-
浏览器驱动
- chrome:
https://registry.npmmirror.com/binary.html?path=chromedriver/
提示:浏览器驱动大版本必须和浏览器版本一致。
- chrome:
-
使用:
windows:1、解压下载的驱动,获取到chromedriver.exe2、将chromedriver.exe复制到python.exe所在目录即可(避免再次将chromedriver.exe添加path变量) mac:1、解压下载的驱动,获取到chromedriver2、将chromedriver复制到/usr/local/bin目录即可。
元素定位
-
什么是元素定位?
通过代码调用方法查找元素
-
元素定位方法
1、id 2、name 3、class 4、tag_name 5、link_text 6、partial_link_text 7、xpath 8、css
-
步骤
1、打开谷歌浏览器 2、输入url 3、找元素及操作 4、关闭浏览器
from selenium import webdriver from time import sleep # 1、打开谷歌浏览器 driver=webdriver.Chrome() # 2、输入url driver.get("https://hmshop-test.itheima.net/Home/user/login.html") # 3、找元素及操作# 4、关闭浏览器 sleep(3) driver.quit()
id定位
-
方法:
driver.find_element_by_id("id值")
-
前置:
标签必须有id属性
-
输入方法:
元素.send_keys("内容")
-
示例:
from selenium import webdriverfrom time import sleep#1、获取浏览器 driver=webdriver.Chrome() #2、打开url driver.get("file:///D:/BaiduNetdiskDownload/web%E8%AF%BE%E5%A0%82%E7%B4%A0%E6%9D%90/web/%E6%B3%A8%E5%86%8CA.html") #3、查找操作元素 #用户名->id->driver.find_element_by_id("id") #元素.send_keys()输入方法 driver.find_element_by_id("userA").send_keys("admin") #密码 driver.find_element_by_id("passwordA").send_keys("123456") #4、关闭浏览器 sleep(3) driver.quit()
name定位
- 方法:
driver.find_element_by_name("name属性值")
- 前置:
标签必须有name属性
- 特点:
当前页面可以重复
- 提示:
由于name属性值可以重复,所以使用时需要查看是否为唯一
class定位
- 方法:
driver.find_element_by_class_name("class属性值")
- 前置:
标签必须有class属性
- 特点:
class属性值可以有多个值
说明:如果标签有多个class值,使用任何一个都可以。如:c11
tag_name定位
- 说明:
根据标签名进行定位
- 方法:
driver.find_element_by_tag_name("标签名")
- 提示:
如果页面存在多个相同标签,默认返回第一个
link_text定位
- 说明:
根据链接文本(a标签)定位
- 方法:
driver.find_element_by_link_name("链接文本")
- 特点:
传入的链接文本,必须全部匹配,不能模糊
partial_link_text定位
- 说明:
根据链接文本(a标签)定位
- 方法:
driver.find_element_by_partial_link_name("链接文本")
- 特点:
传入的链接文本,支持模糊匹配(传入局部文字)
扩展-查找一组元素
- 说明:返回列表格式,要使用需要添加下标或遍历。
- 方法:
driver.find_elements_by_xxxxx()
- 提示:
八大元素定位方法,都可以使用一组元素定位,如果没有搜索到符合标签,返回空列表。
"""
需求:使用定位一组元素的方法+tag_name 将注册a页面所有信息进行填写
"""
from selenium import webdriver
from time import sleep#1、获取浏览器
driver=webdriver.Chrome()
#2、打开url
driver.get("file:///D:/BaiduNetdiskDownload/web%E8%AF%BE%E5%A0%82%E7%B4%A0%E6%9D%90/web/%E6%B3%A8%E5%86%8CA.html")
#3、查找操作元素
inputs = driver.find_elements_by_tag_name("input")
inputs[0].send_keys("admin")
inputs[1].send_keys("123456")
inputs[2].send_keys("16612345678")
inputs[3].send_keys("123456@163.com")
#4、关闭浏览器
sleep(3)
driver.quit()
- 为什么要学习xpath和css?
1、如果标签没有(id\name\class)3个属性,也不是链接标签,只能使用tag_name定位,比较麻烦。
2、方便在工作中查找元素,使用xpath和css比较方便(支持任意属性、层级)来找元素。
Xpath
-
说明:xpath是xml path简称,使用标签路径来定位。
- 绝对路径:从根目录开始,逐级查找标签。
- 相对路径:从任意层级开始,查找标签。
-
策略(方法):
1、路径 2、属性 3、属性与逻辑(多个属性) 4、属性与层级(路径)
-
方法:
driver.find_element_by_xpath("表达式")
-
练习
-
需求
打开注册A.html页面,完成以下操作
1).使用绝对路径定位用户名输入框,并输入:admin
2).暂停2s
3).使用相对路径定位用户名输入框,并输入:123
-
-
实现
from selenium import webdriver
from time import sleep#1、获取浏览器
driver=webdriver.Chrome()
#2、打开url
driver.get("file:///D:/BaiduNetdiskDownload/web%E8%AF%BE%E5%A0%82%E7%B4%A0%E6%9D%90/web/%E6%B3%A8%E5%86%8CA.html")
#3、查找操作元素
#绝对路径
el = driver.find_element_xpath("/html/body/form/div/fieldset/center/p[1]/input")
el.send_keys("admin")
sleep(2)
#清除内容
el.clear()
#相对路径
driver.find_element(By.XPATH,"//p[1]/input").send_keys("123456")
#4、关闭浏览器
sleep(3)
driver.quit()
-
属性
- 单属性:
//*[@属性名="属性值"]
- 多属性:
//*[@属性名="属性值" and @属性名="属性值"]
- 提示:可以使用任何属性。
- 单属性:
-
层级与属性
- 说明:
如果元素现有的属性不能唯一匹配,需要结合层级使用
- 语法:
//父标签/子标签
必须为直属子级//父标签[@属性="值"]//后代标签
父和后代之间可以跨越元素
- 扩展
- 根据显示文本定位:
//*[text()="文本值"]
- 属性值模糊匹配:
//*[contains(@属性名,"属性部分值")]
- 根据显示文本定位:
- 说明:
-
xpath综合练习
from selenium import webdriver
from time import sleep#1、获取浏览器
driver=webdriver.Chrome()
#2、打开url
driver.get("https://hmshop-test.itheima.net/")
#3、查找操作元素
#点击登录链接 文本
driver.driver.find_element_xpath('//*[text()="登录"]').click()
#输入用户名 属性
driver.driver.find_element_xpath('//*[@placeholder="手机号/邮箱"]').send_keys("13600001111")
#密码 包含
driver.driver.find_element_xpath('//*[contains(@placeholder,"密")]').send_keys("123456")
#验证码 多属性
driver.driver.find_element_xpath('//*[@placeholder="验证码" and @name="verify_code"]').send_keys("8888")
#登录按钮 层级
driver.driver.find_element_xpath("//*[@class='login_bnt']/a").click()
CSS选择器
-
说明:css选择器是html查找元素的工具
-
策略:
1、id选择器 2、类选择器 3、标签选择器 4、属性选择器 5、层级选择器
-
id选择器
- 语法:
#id属性值
- 前置:
标签必须有id属性
- 语法:
-
类选择器:
- 语法:
.class属性值
- 前置:
标签必须有class属性
- 语法:
-
标签选择器
- 语法:
标签名
- 提示:
注意标签是否在页面中唯一,否则返回单个或所有
- 语法:
-
属性选择器
- 语法:
[属性名="属性值"]
- 属性:
标签任意属性都可以
- 语法:
-
案例
# 用户名 id选择->#id属性值
driver.find_element_by_css_selector("#userA").send_keys("admin")
# 密码 属性选择器->[属性名='属性值']
driver.find_element_by_css_selector("[name='passwordA']").send_keys("123456")
# 电话 类选择器->.class属性值
driver.find_element_by_css_selector(".telA").send_keys("18600000000")
# 确定 标签选择器-标签名
sleep(2)
driver.find_element_by_css_selector("button").click()
- 层级选择器
- 父子关系:
选择器->选择器
如:#p1>input
- 后代关系:
选择器 选择器
如:#p1 input
- 提示:父子关系:
选择器使用任何一种css选择器(id选择器、类选择器、属性选择器、标签选择器)都可以
- 父子关系:
find_element
- 说明:
八种元素定位方法底层使用的查找元素方法都是find_element,通过By不同的值区分定位方式
- 学习此方法目的:
后期为了查找元素方法的封装
- 示例:
"""
目标:解决find_element使用
场景:后期项目封装中,使用元素查找方法
目的:对后期封装元素查找方法
"""
#3、查找操作元素
driver.find_element(By.ID,"userA").send_keys("admin")
driver.find_element(By.NAME,"passwordA").send_keys("123456")
driver.find_element(By.CLASS_NAME,"telA").send_keys("1360000000")
sleep(2)
driver.find_element(By.TAG_NAME,"button").click()
元素定位总结
结论:1、首推css定位,原因执行速度快。①如果有ID属性,使用#id②没有id属性,使用其他有的属性(能代表唯一的属性)③如果属性都代表不了唯一,使用层级2、如果css解决不了,使用Xpath
元素操作
1、操作方法
2、获取方法
常用操作方法
元素=driver.find_element()
- 点击:元素.click()
- 输入:元素.send_keys(内容)
- 清空:元素.clear()
获取元素信息
-
方法
- 获取大小:
元素.size
- 获取文本:
元素.text
- 获取属性:
元素.get_attribute('属性名')
- 元素是否可见:
元素.is_displayed()
- 元素是否可用:
元素.is_enabled()
- 元素是否被选中:
元素.is_selected
- 获取大小:
-
案例
#获取大小 元素.size
user = driver.find_element(By.CSS_SELECTOR,"#userA").size
print("用户名输入框的大小:",user)
#获取内容 元素.text
a_text=driver.find_element(By.TAG_NAME,"a").text
print("第一个a标签的文本:",a_text)
#获取属性 超链接地址
a_href= driver.find_element(By.TAG_NAME,"a").get_attribute("href")
print("第一个a标签的链接:",a_href)
#判断span标签是否可见 元素.is_displayed
span = driver.find_element(By.TAG_NAME,"span").is_displayed()
print("span是否可见:",span)
#判断取消按钮是否可用 is_enabled
btn_is_enable = driver.find_element(By.CSS_SELECTOR,"#cancelA").is_enabled()
print("取消按钮是否可用:",btn_is_enable)
#旅游是否选中 is_selected
is_selected = driver.find_element(By.CSS_SELECTOR,"#lyA").is_selected()
print("旅游是否被选中:",is_selected)
浏览器操作
浏览器常用api
- api
- 案例
from selenium import webdriver
from selenium.webdriver.common.by import By
from time import sleep#1、获取浏览器
driver=webdriver.Chrome()
#2、打开url
driver.get("file:///D:/BaiduNetdiskDownload/web%E8%AF%BE%E5%A0%82%E7%B4%A0%E6%9D%90/web/%E6%B3%A8%E5%86%8CA%E9%BB%84%E8%89%B2.html")
#3、查找操作元素
#最大化浏览器
driver.maximize_window()
sleep(3)
#设置窗口大小
driver.set_window_size("500","700")
sleep(3)
#设置窗口位置
driver.set_window_position("0","500")
sleep(3)
#点击新浪
driver.find_element(By.PARTIAL_LINK_TEXT,"新浪").click()
sleep(3)
#后退
driver.back()
sleep(3)
#前进
driver.forward()
sleep(3)
#刷新
driver.refresh()
#4、关闭浏览器
sleep(3)
driver.quit()
浏览器常用获取信息api
- api
重点:1、close关闭当前焦点所在窗口2、quit关闭的是浏览器3、启动哪个窗口,默认焦点就在哪个窗口,如果需要切换到别的窗口,需要调用api方法切换。
案例
from selenium import webdriver
from selenium.webdriver.common.by import By
from time import sleep#1、获取浏览器
driver=webdriver.Chrome()
#2、打开url
driver.get("file:///D:/BaiduNetdiskDownload/web%E8%AF%BE%E5%A0%82%E7%B4%A0%E6%9D%90/web/Register.html")
#3、查找操作元素
#最大化浏览器
driver.maximize_window()
#获取当前窗口标题
print("当前窗口title:",driver.title)
#获取当前窗口url
print("当前窗口url:",driver.current_url)
sleep(3)
driver.find_element(By.PARTIAL_LINK_TEXT,"注册A网页").click()
#获取当前窗口标题
print("当前窗口title:",driver.title)
#获取当前窗口url
print("当前窗口url:",driver.current_url)
sleep(3)
#关闭当前窗口
driver.close()
#4、关闭浏览器
sleep(3)
driver.quit()
页面交互操作
下拉框
- 需求
- 方式
1、使用css或xpath(推荐)
2、使用专属select类
- 方式1
# 点击广州
driver.find_element(By.CSS_SELECTOR,"[value='gz']").click()
sleep(2)
# 点击上海
driver.find_element(By.CSS_SELECTOR,"[value='sh']").click()
sleep(2)
# 点击北京
driver.find_element(By.CSS_SELECTOR,"[value='bj']").click()
- 方式2(了解)
from selenium import webdriver
from time import sleep
from selenium.webdriver.common.by import By
from selenium.webdriver.support.select import Select
#1、获取浏览器
driver=webdriver.Chrome()
#2、打开url
driver.get("file:///D:/BaiduNetdiskDownload/web%E8%AF%BE%E5%A0%82%E7%B4%A0%E6%9D%90/web/%E6%B3%A8%E5%86%8CA%E9%BB%84%E8%89%B2.html")#使用select类来实现
#1、定位下拉框元素 select
el=driver.find_element(By.CSS_SELECTOR,"#selectA")
#实例化select对象
select = Select(el)
#3、使用下标定位广州
select.select_by_index(2)
sleep(2)
# 使用value定位上海
select.select_by_value("sh")
sleep(2)
#使用文本定位北京
select.select_by_visible_text("A北京")
#4、关闭浏览器
sleep(3)
driver.quit()
弹出框
- 为什么要处理弹窗?
如果页面操作过程中,有弹窗出现,不处理,无法继续对页面操作。
- 弹窗类型?
1、js原生弹窗(警告框、输入框、提示框)必须处理
2、开发使用标签自定义弹窗效果(不用处理,正常操作即可。)
- 如何处理?
1、获取弹窗对象
2、点击同意或取消方法
- 示例
#点击弹窗
driver.find_element(By.ID,"alerta").click()
sleep(2)
#获取弹窗对象
el = driver.switch_to.alert
#处理弹窗 同意/取消
# el.dismiss()# 取消
print("弹出文本:",el.text)
el.accept() #同意
sleep(2)
#输入用户名
driver.find_element(By.CSS_SELECTOR,"#userA").send_keys("admin")
滚动条
- 为什么要操作滚动条?
有些页面场景,必须滚动条拉到最底下才能做某事
如:注册页面,阅读完需求,协议才能勾选,此时就必须拖到滚动条。
- 步骤
1、定义js语句
2、调用执行JS方法
- 示例
#设置窗口大小
driver.set_window_size(500,500)
sleep(2)
#js->向下滑动10000像素
# js_down="window.scrollTo(0,10000)"
#动态执行滑到底部 向下滑动滚动条高度
#js(0,10000)第1个0为水平滚动条
js_down="window.scrollTo(0,document.body.scrollHeight)"
#执行js方法
driver.execute_script(js_down)
sleep(2)
#js->向上
js_top="window.scrollTo(0,0)"
driver.execute_script(js_top)
鼠标操作
- 方法
1、双击方法
2、右击方法
3、悬停
4、拖拽
- 示例
from selenium.webdriver import ActionChains
#获取ActionChains对象
action =ActionChains(driver)
#练习1
#查找注册按钮
el= driver.find_element(By.CSS_SELECTOR,"button")
sleep(2)
#调用悬停方法
action.move_to_element(el).perform()#练习2
username =driver.find_element(By.CSS_SELECTOR,"#userA")
#右击
action.context_click(username).perform()#练习3
driver.find_element(By.CSS_SELECTOR,"#userA").send_keys("admin")
sleep(3)
#双击
action.double_click(username).perform()
#拖拽
#获取ActionChains对象
action = ActionChains(driver)
div1 = driver.find_element(By.CSS_SELECTOR,"#div1")
div2 = driver.find_element(By.CSS_SELECTOR,"#div2")
action.drag_and_drop(div1,div2).perform()
其他重要API
- 什么是等待?
代码执行过程中,第一次未找到元素,先不抛出异常。激活等待时间,在等待过程中如果找到元素就执行。
- 为什么要等待?
由于网络或配置原因,导致元素未加载出来,而代码已执行,会触发异常。
- 元素等待类型
1、隐式等待
2、显式等待
3、强制等待--->time.sleep(秒)
隐式等待
- 说明:
针对全部元素生效
- 方法:
driver.implicitly_wait(秒)
- 提示:在项目中,如果未封装自动化框架时,推荐使用。
显式等待
- 说明:
针对单个元素生效,可用修改查找频率和超时时间
- 特点:
查找并返回元素
- 用法
from selenium.webdriver.support.wait import WebDriverWait
#2、显式等待->返回查找到的元素
el = WebDriverWait(driver,10,0.5).until(lambda x:x.find_element(By.CSS_SELECTOR,"#userA"))
el.send_keys("admin")
强制等待
- 语法:
sleep(10)
- 提示:
执行到这句必须等待10s,不灵活。
- 示例:
from time import sleep
sleep(10)
等待对比
操作frame框架的元素
-
frame(iframe) 标签作用–是什么
在页面中加载另一个页面
-
为什么处理iframe(frame)?
焦点默认在启动页面,如果不处理iframe,无法操作iframe嵌入的页面元素。
-
如何处理?
- 步骤
1、切换到iframe driver.switch_to.frame(iframe元素) 2、操作元素 3、回到默认页面 driver.switch_to.default_content()
-
示例
#获取注册A iframe元素
A = driver.find_element(By.CSS_SELECTOR,"#idframe1")
#1、切换到A
driver.switch_to.frame(A)
#2、注册A操作
driver.find_element(By.CSS_SELECTOR,"#userA").send_keys("admin")#3、回到默认目录,注册实例.html
driver.switch_to.default_content()#4、获取注册B iframe元素
B = driver.find_element(By.CSS_SELECTOR,"#idframe2")
#5、切换到B
driver.switch_to.frame(B)#注册B操作
driver.find_element(By.CSS_SELECTOR,"#userB").send_keys("admin")
切换多窗口
- 什么是多窗口?
通过a链接,如果打开方式新窗口打开,那么就会出现多窗口。
- 为什么要切换?
selenium默认启动时,所有焦点都在启动窗口,那么意味着无法操作其他窗口的标签。
-
如何切换?
-
步骤:
1、获取窗口句柄 driver.window_handles 2、使用句柄切换窗口driver.switch_to.window(handle) 句柄:窗口的唯一标识符
-
示例:
""" 为什么要处理多窗口?--selenium默认焦点在启动窗口,要操作其他窗口必须处理。 需求:1、打开注册示例页面2、点击注册A网页链接3、填写注册A网页内容 """ print("操作之前所有窗口的句柄:",driver.window_handles) driver.find_element(By.LINK_TEXT,"注册A网页").click() handles=driver.window_handles print("操作之后所有窗口的句柄:",driver.window_handles) #重点:切换窗口 driver.switch_to.window(handles[1]) #填写注册A网页 用户名 driver.find_element(By.CSS_SELECTOR,"#userA").send_keys("admin")
-
-
多窗口之间切换工具封装
from selenium import webdriver
from selenium.webdriver.common.by import By
from time import sleep
#1、获取浏览器
driver=webdriver.Chrome()
#2、打开url
driver.get("file:///D:/BaiduNetdiskDownload/web%E8%AF%BE%E5%A0%82%E7%B4%A0%E6%9D%90/web/Register.html")"""
为什么要处理多窗口?--selenium默认焦点在启动窗口,要操作其他窗口必须处理。
需求:如何随心所欲切换窗口?
思路:1、获取所有窗口句柄2、切换窗口3、获取当前所在窗口的title4、判断title是否为需要的窗口5、执行代码
需求:1、打开注册示例页面2、点击注册A页面 注册B页面3、在A网页和B网页中,输入admin
"""
def switch_window(title):#1、获取所有窗口句柄handles = driver.window_handles#2、遍历句柄进行切换for handle in handles:#操作driver.switch_to.window(handle)#获取当前窗口title,并且判断是否自己需要的窗口if driver.title == title:#操作代码return "已经找到{}窗口,并且已切换成功".format(title)title_A = "注册A"
title_B = "注册B"
#打开注册A网页和B网页
driver.find_element(By.LINK_TEXT,"注册A网页").click()
driver.find_element(By.LINK_TEXT,"注册B网页").click()
#填写注册A网页 用户名
switch_window(title_A)
driver.find_element(By.CSS_SELECTOR,"#userA").send_keys("admin")
#填写注册B网页 用户名
switch_window(title_B)
driver.find_element(By.CSS_SELECTOR,"#userB").send_keys("admin")sleep(13)
driver.quit()
- 小结
如果定位不到元素怎么办?
截图
- 什么是截图?
当前ui页面,截图保存
- 为什么要截图?
出错后,方便查看直观错误原因。
- 如何截图?
driver.get_screenshot_as_file("XXX.png")
- 扩展-图片命名添加时间戳
driver.get_screenshot_as_file("error_{}.png".format(time.strftime("%Y_%m_%d %H_%M_%S")))
- 示例:
driver.find_element(By.CSS_SELECTOR,"#userA").send_keys("admin")
driver.find_element(By.CSS_SELECTOR,"#passwordA").send_keys("123456")
driver.find_element(By.CSS_SELECTOR,"#telA").send_keys("166123456")
driver.find_element(By.CSS_SELECTOR,"#emailA").send_keys("123@qq.com")
#截图
driver.get_screenshot_as_file("register.png")
driver.get_screenshot_as_file("error_{}.png".format(time.strftime("%Y_%m_%d %H_%M_%S")))
验证码处理
- 处理方式:
1、去除验证码
2、使用万能验证码
3、使用图片识别技术(识别效率低)
4、使用cookie
- cookie
- 说明:由服务器生成,存储在客户端的登录凭证。
- 使用:
1、获取cookie # 获取所有driver.get_cookies()
2、添加cookie # driver.add_cookie(data)
- 示例
from selenium import webdriver
from time import sleepdriver = webdriver.Chrome()
driver.get("https://www.baidu.com")
driver.maximize_window()
#添加cookie
data={"name":"BDUSS","value":"QzeEJKQVV3lZ5anh1QlNDWG43YjltjD5rnUyt4yAOdgmGbnYJhmQ1"}
driver.add_cookie(data)
#暂停5秒
sleep(5)
#刷新
driver.refresh()
sleep(3)
driver.quit()