Python+selenium 【第六章】UI自动化框架操作测试对象
层级定位
在实际的项目测试中,经常会遇到无法直接定位到需要选取的元素,但是其父元素比较容易定位,通过定位父元素再遍历其子元素选择需要的目标元素,或者需要定位某个元素下所有的子元素。
层级定位的思想是先定位父对象,然后再从父对象中精确定位出其我们需要选取的后代元素。
- 语法举例
driver.find_element_by_id(‘***’).find_element_by_link_text(‘***’)
示例代码
- demo_father_son.py
# -*- coding: utf-8 -*-
# @Time : 2021/12/29 20:02
# @Author : Limusen
# @File : demo_father_son
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
# 执行这个语句会报错
# driver.find_element(By.XPATH,'//*[@id="form"]/span[1]').send_keys("ssdasd")
# 执行这个语句不会报错
# driver.find_element(By.XPATH,'//*[@id="kw"]').send_keys("ssdasd")
# 根据层级关系查找
driver.find_element_by_css_selector("span.bg.s_ipt_wr.new-pmd.quickdelete-wrap").find_element_by_id(
"kw").send_keys("测试父子级定位")
iframe框架
定位frame中的对象:在web应用中经常会出现frame嵌套的应用,假设页面上有A,B两个frame,其中B在A内,那么定位B中的内容则需要先到A,再到B。
switch_to_frame方法可以把当前定位的主题切换到frame里,在frame里实际是嵌套了另外一个页面,而webdriver每次只能在一个页面识别,所以需要用switch_to_frame方法去获取frame中嵌套的页面。
- 举例:
driver.switch_to.frame(‘frame1’)
#移动到id为frame1的frame上printdriver.find_element_by_css_selector("#div1").text
driver.switch_to.default_content()#将识别的主体切换出frame
printdriver.find_element_by_css_selector("#id1").text
- 备注:
switch_to.frame的参数必须是id或者是name,所以一个frame只要有id和name处理起来很容易。
如果没有的话,两种解决思路:
1、让开发加上id或者name
2、使用xpath等方式定位然后实现跳转
示例代码
# -*- coding: utf-8 -*-
# @Time : 2021/12/29 20:15
# @Author : Limusen
# @File : demo_baidu_login
import time
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://sahitest.com/demo/iframesTest.htm")
driver.implicitly_wait(10)
# # 直接定位到link位置
# driver.find_element_by_xpath("/html/body/table/tbody/tr/td[1]/a[1]").click() # 发现脚本会报错 找不到这个元素
# 定位到iframe 当前是定位到左边框架
element = driver.find_element_by_xpath('//iframe[@style="float:left;margin:20px;"]')
driver.switch_to.frame(element)
time.sleep(2)
driver.find_element_by_xpath('/html/body/table/tbody/tr/td[1]/a[1]').click()
# 跳出框架
driver.switch_to.default_content()
time.sleep(2)
# 定位iframe框架中的iframe框架
element = driver.find_element_by_xpath('//div[@id="another"]/iframe')
driver.switch_to.frame(element)
time.sleep(2)
driver.find_element_by_xpath('/html/body/table/tbody/tr/td[1]/a[1]').click()
直接定位到link位置 driver.find_element_by_xpath("/html/body/table/tbody/tr/td[1]/a[1]").click()
发现脚本会报错 找不到这个元素定位到iframe 当前是定位到左边框架
#定位iframe框架中的iframe框架
element = driver.find_element_by_xpath(’//div[@id=“another”]/iframe’)
driver.switch_to.frame(element)
操作浏览器弹出框
alert/confirm/prompt处理:
WebDriver中处理原生JS的alertconfirm以及prompt非常方便。具体思路是使用switchTo.alert()方法定位到当前的alert/confirm/prompt(这里注意当前页面只能同时含有一个控件,如果多了会报错的,所以这就需要一一处理了),然后在调用Alert的方法进行操作
Alert提供了以下几个方法:
- text:返回alert/confirm/prompt中的文字内容
- accept:点击确认按钮
- dismiss:点击取消按钮如果有取消按钮的话
- sendKeys:向prompt中输入文字
语法举例:
driver.find_element_by_id(“alert”).click() time.sleep(3)
driver.switch_to.alert.accept()
driver.find_element_by_id(“confirm”).click() time.sleep(3)
driver.switch_to.alert.dismiss()
driver.find_element_by_id(“prompt”).click() time.sleep(3)
driver.switch_to.alert.send_keys(“123456”) time.sleep(3)
driver.switch_to.alert.accept()
备注:send_keys这个方法在chromedriver中输入后不会显示。
示例代码
- demo_js_09.py
# -*- coding: utf-8 -*-
# @Time : 2021/12/30 10:22
# @Author : Limusen
# @File : demo_iframe_09
import time
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://sahitest.com/demo/jsPopup.htm")
driver.implicitly_wait(5)
driver.find_element_by_xpath('//button').click()
# 处理alert弹框
time.sleep(2)
driver.switch_to.alert.accept() # 确认按钮
time.sleep(2)
# 取消按钮
driver.switch_to.alert.dismiss()
time.sleep(2)
driver.switch_to.alert.send_keys("测试一下输入")
time.sleep(2)
driver.switch_to.alert.dismiss()
#备注:send_keys这个方法在chromedriver中输入后不会显示。
下拉框详解
下拉框处理:
web页面上经常会有下拉框,对下拉框的处理比较简单,一般分为两种情况:
- 下拉框通过元素定位识别
- 举例:
driver.find_element(By.XPATH,’//option[@value=“mango”]’).click()
上面的元素为下拉框中的选项。
- 创建一个select的对象,然后通过相应方法处理
- 举例:
selectElement=driver.find_element(By.XPATH,’//select[@id=“Selector”]’)
s=Select(selectElement)
s.select_by_index(2) #索引定位,索引从0开始
time.sleep(2)
s.select_by_value(“mango”)#value属性的值
time.sleep(2)
s.select_by_visible_text(“桔子”) #可见文本内容
示例代码
# -*- coding: utf-8 -*-
# @Time : 2021/12/30 10:22
# @Author : Limusen
# @File : demo_selector_10
import time
import random
from selenium import webdriver
from selenium.webdriver.support.select import Select
driver = webdriver.Chrome()
driver.get("https://sahitest.com/demo/selectTest.htm")
driver.implicitly_wait(5)
# 定位到下拉框元素
selectElement = driver.find_element_by_xpath("//select[@id='s3Id']")
s = Select(selectElement)
s.select_by_index(2) # 根据下标选择下拉框第三个元素
time.sleep(2)
s.select_by_value("o4val") # 元素的value值
time.sleep(2)
s.select_by_visible_text("o3") # 可见文本内容
# 定位到元素列表然后随机选择一个元素选择
time.sleep(2)
selectElement= driver.find_element_by_xpath("//select[@id='s1']")
time.sleep(2)
selectElement.click()
time.sleep(2)
elements = driver.find_elements_by_xpath("//select[@id='s1']/option")
time.sleep(2)
random.choice(elements).click()
调用js操作元素
- 调用javascript:
当webdriver遇到无法完成的操作时候,这个时候可以使用javascript来完成,webdriver提供了execute_script()接口来调用js代码。
- 执行js有两种场景:
- 一种是在页面上直接执行js
- 另一种是在某个已经定位的元素上执行js
- 举例:
driver.execute_script(‘alert(“hello!!”);’)#弹出窗口
driver.execute_script(“arguments[0].style.border=‘5pxsolidred’”,wl)#加边框
js=“varuser_input=document.getElementById(‘su’).getAttribute(‘id’);
returnuser_input;”driver.execute_script(js)#识别并获取对象属性
driver.execute_script(“document.body.scrollTop=10000;”)#浏览器滚动条滚动
Js=‘arguments[0].removeAttribute(“value”);’#移除元素的value属性
Js=‘arguments[0].setAttribute(“value”,“newdream”);’#设置元素的value属性
driver.execute_script(js,wl)
示例代码
# -*- coding: utf-8 -*-
# @Time : 2021/12/30 11:45
# @Author : Limusen
# @File : demo_page_js_11
# 执行js脚本
import time
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
driver.maximize_window()
driver.implicitly_wait(10)
time.sleep(2)
# 执行js脚本
driver.execute_script("alert('测试页面弹框')")
time.sleep(2)
driver.switch_to.alert.accept()
wl = driver.find_element_by_xpath('//*[@id="kw"]')
driver.execute_script("arguments[0].style.border='5px solid red'", wl) # 加边框
time.sleep(2)
# 获取元素的属性
js = "var user_input= document.getElementById('su').getAttribute('id'); return user_input;"
driver.execute_script(js)
id = driver.execute_script('return document.getElementById("su").getAttribute("id");')
value = driver.execute_script('return document.getElementById("su").getAttribute("value");')
class_name = driver.execute_script('return document.getElementById("su").getAttribute("class");')
name = driver.execute_script('return document.getElementById("kw").getAttribute("name");')
print(id)
print(value)
print(class_name)
print(name)
# 滚动条操作,封装成函数
driver.find_element_by_name("wd").send_keys("测试一下")
time.sleep(2)
driver.find_element_by_id("su").click()
time.sleep(1)
js = "window.scrollBy(0,500)"
driver.execute_script(js)
time.sleep(2)
js = "window.scrollBy(0,500)"
driver.execute_script(js)
js = "window.scrollBy(0,-1000)"
driver.execute_script(js)
# def scoll(driver, heigh):
# time.sleep(2)
# js = "window.scrollBy(0," + str(heigh) + ")"
# driver.execute_script(js)
#
#
# scoll(driver, 500)
# time.sleep(2)
# scoll(driver, 1000)
# 改元素的属性
el = driver.find_element_by_name("wd")
js = 'arguments[0].removeAttribute("id")'
driver.execute_script(js,el)
js = 'arguments[0].setAttribute("value","newdream")'
driver.execute_script(js)
time.sleep(2)
driver.quit()
页面切换句柄
- 浏览器多窗口处理:
有时候我们在测试一个web应用的时候会出现多个浏览器窗口的情况,webdriver提供了相应的解决方案,如下:首先要获得每一个窗口的唯一标识符号(句柄),通过获得的句柄来区分不同的窗口,从而对不同窗口上的元素进行操作。
- 举例:
now_handle=driver.current_window_handle#获取当前窗口句柄
driver.find_element_by_css_selector('a.pass-reglink').click()
time.sleep(2)
all_hands=driver.window_handles#获取所有窗口的句柄
for hands in all_hands:
if hands!=now_handle:
driver.switch_to_window(hands)#通过句柄跳转窗口
driver.find_element_by_name("account").send_keys("123456")
driver.close()#关闭新打开的窗口
driver.switch_to_window(nowhandle)#回到之前的窗口
driver.find_element_by_css_selector("a.close-btn").click()
示例代码
# -*- coding: utf-8 -*-
# @Time : 2021/12/30 11:45
# @Author : Limusen
# @File : demo_page_js_11
import time
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
driver.maximize_window()
driver.implicitly_wait(10)
time.sleep(2)
# 获取百度的句柄
now_handle = driver.current_window_handle
print(now_handle)
# 点击hao123
driver.find_element_by_xpath('//*[@id="s-top-left"]/a[2]').click()
# 获取所有句柄
all_handle = driver.window_handles
print(all_handle)
# 切换句柄 切换到新句柄当中
driver.switch_to.window(all_handle[1])
time.sleep(1)
driver.find_element_by_xpath('//*[@id="search"]/form/div[2]/input').send_keys("切换句柄之后输入")
time.sleep(1)
driver.find_element_by_xpath('//*[@id="search"]/form/div[3]/input').click()
# 跳回原来页面
driver.switch_to.window(now_handle)
通过处理cookie信息,绕过登录
- cookie处理:
利用cookie完成网站的免密码应用代码思路:
第一阶段:
打开网站的登录页面获取登录之前的cookie等待60s,这个时间手动去输入用户名、密码、验证码登录获取登录之后的cookie把登录之后的cookie与登录之前的cookie打印并进行对比找出登录之后不同的cookie或增加的cookie信息
第二阶段:
新编写一个脚本打开网站的登录页面用add_cookie()方式去逐项增加登录之后不同的cookie刷新网站,即可完成自动登录操作
示例代码
# -*- coding: utf-8 -*-
# @Time : 2021/12/30 11:45
# @Author : Limusen
# @File : demo_page_js_11
import time
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://www.cnblogs.com/")
driver.implicitly_wait(10)
# # 获取cookie
# time.sleep(60)
# cookies = driver.get_cookies()
# for cookie in cookies:
# print(cookie)
# 添加cookies
time.sleep(2)
driver.add_cookie({'domain': '.cnblogs.com', 'httpOnly': True, 'name': '.CNBlogsCookie', 'path': '/', 'secure': False, 'value': '1314E64052AFA5D9C750AD2E9E465A723592E9CB678E6DA1B68F8535EB07C9C4971BB4B5C1AEF448245C67A196B926C14E0A7ADB11E22826E3719DC967E881A44D1021EBC1E1F3B489FBDEE52487A7B6A3BCE717'})
driver.add_cookie({'domain': 'www.cnblogs.com', 'httpOnly': True, 'name': '.AspNetCore.Antiforgery.b8-pDmTq1XM', 'path': '/', 'secure': False, 'value': 'CfDJ8GsLOKiGtk1Au0UP1SouGdWCoD8gCqTvivwLXs6zGnDbTlG2hDcH7vXTjBcuLfr2ORpoZDwNyPOYuRFEEUWa4P91FQz7HCl2AaAEBTZJs6fAf4QtmrVZ7NfGHHxdxJC5AGd3dDUUvmWLjYuUwOPGyYo'})
driver.add_cookie({'domain': '.cnblogs.com', 'expiry': 1703915500, 'httpOnly': False, 'name': '_ga', 'path': '/', 'secure': False, 'value': 'GA1.2.285569987.1640843473'})
driver.add_cookie({'domain': '.cnblogs.com', 'httpOnly': False, 'name': 'Hm_lpvt_866c9be12d4a814454792b1fd0fed295', 'path': '/', 'secure': False, 'value': '1640843500'}
)
driver.add_cookie({'domain': '.cnblogs.com', 'expiry': 1672379500, 'httpOnly': False, 'name': 'Hm_lvt_866c9be12d4a814454792b1fd0fed295', 'path': '/', 'secure': False, 'value': '1640843472'})
driver.add_cookie({'domain': '.cnblogs.com', 'expiry': 1703915499, 'httpOnly': False, 'name': '_ga_3Q0DVSGN10', 'path': '/', 'secure': False, 'value': 'GS1.1.1640843475.1.1.1640843499.36'})
driver.add_cookie({'domain': '.cnblogs.com', 'httpOnly': True, 'name': '.Cnblogs.AspNetCore.Cookies', 'path': '/', 'secure': False, 'value': 'CfDJ8GsLOKiGtk1Au0UP1SouGdUrAXCnnNWytA-q0doJUXW33Asw81g-6FAy__3mnkDZUSq-cYPkDXtJo9RCzXl7CfcAkX8no75DcaKyPDTlB52nME1_YNqBXaPjJxNQ_NKBnUIu0z7bWDX2Nlr3jKk8FtHfxXIM6GMIN5yn0RW2zVqZyGvWSPG6kwc68CnSNAhFArV8YZBrmJHrLGPp89F3kJkHQe8XotQjscvaj2E-FGHPbMPTXhh8U3iveHf8MDiAChZr2dkPhbe6VWp1RxWqgrkHitnaayzT_qY66qimE3_K2_B-7uHO23qUgQY8UFpbIk0zH-IxnKtQxWG2M-kk_X_q3b9oOCRx0GXrLYvRONQVzkgHIxu6c_BpEN3Ol-yHgr_EpFRtaDwZLi_7tFOVVwkyOWdBmVHHq220KG_LKloS0E2aPLBRmOVKvkGIjct8lTzCNmALcT0_NinO8oEhPqFmcMrtZrW-J5qJUMoo7MUZhqjd30ndzfxZRaawU1Crvfa2t-NBlQ1ipcpAmrAeSUGxsJRP_GRTFCTOgm0Tye6-'})
driver.add_cookie({'domain': '.cnblogs.com', 'expiry': 1640929900, 'httpOnly': False, 'name': '_gid', 'path': '/', 'secure': False, 'value': 'GA1.2.740095988.1640843473'}
)
driver.refresh()
- 登录博客园之后的cookie
- 将cookie添加到driver驱动当中
- 刷新页面
总结
本章节主要讲述了层级定位,iframe框架切换,句柄的切换,js的操作,以及如果使用cookies绕过登录,下一章节我们将学习unittest的一些操作
敬请期待~
代码地址
https://gitee.com/todayisgoodday/PythonSelenium
博客园地址
https://www.cnblogs.com/yushengaqingzhijiao/category/2000515.html