web自动化测试总结

学习目标:

字体标红方法

<font color=red>字体文字</font>

-撑握元素定位的方法(id、name、class_name、tag_name、link_text、partial_link_text)

-掌握xpath和CSS元素定位方式

-掌握元素及浏览器操作

一、元素定位(6+2)

1.1 如何进行元素定位?

  • 元素: 由标签头+标签尾+标签头和标签尾包括的文本内容

  • 元素的信息:就是指元素的标签名以及元素的属性

  • 元素的层级结构:就是指元素之间相互嵌套的层级结构

元素定位最终就是通过元素的信息或者元素的层级结构来进行元素定位。

1.2 元素定位

  • id定位
  • name定位
  • class_name定位
  • tag_name定位
  • link_text定位
  • partail_link_text定位
  • xpath定位
  • css定位

1.2.1 ID定位

  • 通过元素的ID属性值来进行元素定位 ,在html标准规范中 ID值是唯一的

说明: 元素要有ID属性

  • 定位方法: find_element_by_id(id) # id参数表示的是id的属性值

1.2.2 name定位

  • 通过元素的name属性值为进行元素定位 name属性值 在HTML页面中,是可以重复的。

说明:元素要有name属性

  • 定位方法: find_element_by_name(name) # name 参数表示的是name的属性值

1.2.3 class_name定位

  • 通过元素的class属性值进行元素定位 class属性值是可重复的

说明:元素必须要有class属性

  • 定位方法: find_element_by_class_name(class_name)# class_name参数表示的是class的其中一个属性值

补充:处理多个class_name

当元素的class属性有多个值时,处理方法:

<input type="email" name="emailA" class="emailA dzyxA" placeholder="请输入电子邮箱">

1,只需定义任意一个 属性值

driver.find_element_by_class_name("dzyxA").send_keys("128312@qq.com")
或
driver.find_element_by_class_name("emailA").send_keys("128312@qq.com")

2.通过css_selector() 代替class_name()方法,使用多个class_name 来定位

  • 处理方法:在每个class_name前面加上小数点接口
  • 例如:("emailA dzyxA")-----(".emailA.dzyxA")
driver.find_element_by_css_selector(".emailA.dzyxA").send_keys("128217@qq.com")

3.通过xpath 定位

  • 处理方法:要把多个class属性值都带上
//*[@class='emailA dzyxA']

driver.find_element_by_xpath
("//*[@class='emailA dzyxA']").send_keys("128217@qq.com")

如果//*[@class='dzyxA']或者//*[@class='emailA']定位不到

1.2.4 tag_name定位

补充:处理相同标签元素

  • 通过元素的标签名称进行定位, 在同一个html页面当中,相同标签元素会有很多。

这种定位元素的方式不建议大家在工作当中使用。

  • 定位方法: find_element_by_tag_name(tag_name) #tag_name表示的是元素的标签名称。

如果有重复的元素,定位到的元素默认都是第一个元素

示例:通过input标签定位邮箱输入框(邮箱的input标签是 页面的第四个,所以下标是3)

driver.find_elements_by_tag_name("input")[3].send_keys("123@qq.com")

补充:find_element() 和find_elements()区别

find_element()  表示找到页面中满足条件的第一个元素
find_elements()  表示找到页面中所有符合条件的页面元素
关系:用下标,从0开始计算的
find_element()=find_elements()[0]

补充:xpath中直接写下标(下标从1开始的,不是列表中从0开始),就不用elements

<div data-v-03a50258="" class="pic">
    <div data-v-03a50258="" class="pic-item">
        <img data-v-03a50258="" src="/img/login/wechat.png"> 
        <p data-v-03a50258="">微信登录</p>
    </div>
    <div data-v-03a50258="" class="pic-item">
        <img data-v-03a50258="" src="/img/login/pc.png"> 
        <p data-v-03a50258="">密码登录</p>
    </div>
    <div data-v-03a50258="" class="pic-item">
        <img data-v-03a50258="" src="/img/login/qq.png"> 
        <p data-v-03a50258="">QQ登录</p>
    </div>
</div>

//div[@class='pic-item'][2]//p  

  • 通过超链接的全部文本信息进行元素定位 ,主要用来定位a标签

定位方法: fifind_element_by_link_text(link_text) # link_text

  • 参数代表的是a标签的 全部 文本内容。
<a href="http://www.sina.com.cn">新浪</a>
driver.find_element_by_link_text("新浪").click()
  • 通过超链接的局部文本信息进行元素定位,主要用来定位a标签

定位方法:

  • find_element_by_partial_link_text(partial_link_text)
    • partial_link_text表示的是a标签 的 **局部 ** 文本内容
<a href="http://www.sina.com.cn" id="fw" target="_blank">访问 新浪 网站</a>
driver.find_element_by_partial_link_text("访问").click()

1.2.7 定位一组元素(elements)

  • 定位一组元素的方法:

    • find_elements_by_id(id)
    • find_elements_by_tag_name(tag_name)
  • 定位一组元素返回的值是一个列表

  • 可以通过下标来使用列表中的元素

  • 下标是从0开始。

find_element()  表示找到页面中满足条件的第一个元素
find_elements()  表示找到页面中所有符合条件的页面元素
关系:用下标,从0开始计算的
find_element()=find_elements()[0]
示例:
driver.find_elements_by_tag_name("input")[3].send_keys("123@qq.com")

二、元素定位Xpath、CSS

1.xpath元素定位

1.1 什么是xpath

  • 总结:xpath是用来在xml文件中进行元素定位的标记语言,html是一种特殊的xml,所以xpath也可以用在html中

1.2 Xpath定位策略

  • 路径定位
  • 属性定位
  • 属性与逻辑结合
  • 属性与层级结合

定位方法: find_element_by_xpath(xpath) # xpath表达式

按Ctrl+F 可以在搜索框对xpath和css表达式进行校验

1.2.1 路径定位

  • 绝对路径 :
    • 表达式是以 /html开头,元素的层级之间是以 / 分隔
    • 相同层级的元素可以使用下标,下标是从1开始.
    • 需要列出元素所经过的所有层级元素 , 工作当中, 一般不使用绝对路径
    • 例:/html/body/div/fifieldset/form/p[1]/input

示例: 通过xpath的绝对路径定位用户名输入框并输入admin

driver.find_element_by_xpath("/html/body/div/fieldset/form/p/input").send_keys("admin")
  • 相对路径 :
    • 匹配任意层级的元素, 是以 //tag_name或者//* 开 头
    • 也可以使用下标,下标是从1开始。
    • 例子://p[5]/button //*[@id="telA"]

示例:通过xapth的相对路径定位密码输入框并输入123456

driver.find_element_by_xpath('//*[@id="passwordA"]').send_keys("123456")
  • 或者:
driver.find_element_by_xpath("//form/p[2]/input").send_keys("123456")

1.2.2 元素属性定位

  • // 或者 //tag_name //*[@attribute='value']
  • attribute表示的是元素的属性名,value表示的是元素对应属性值

如果使用class的属性进行元素定位,需要用到class里面所有的值

示例:利用元素的属性信息精确定位用户名输入框,并输入:admin

<input type="text" name="userA" id="userA" placeholder="请输入用户名">
driver.find_element_by_xpath('//*[@placeholder="请输入用户名"]').send_keys("admin")

1.2.3 属性与逻辑结合定位

  • //* 或者 //tag_name 开头 //*[@attribute1='value1' and@attribute2='value2']

示例: 使用属性与逻辑结合定位策略,在test1对应的输入框里输入:admin

<input type="text" name="user" class="login">
driver.find_element_by_xpath("//input[@name='user' and @class='login']").send_keys("admin")

1.2.4 属性与层级结合定位(重点)

  • 是以 //* 或者 //tag_name 开头 //p[@id='pa']/input

    在任意层给当中,都可以结合属性来使用

示例2:使用层级与属性结合定位策略,在test1对应的输入框里输入:admin

driver.find_element_by_xpath('//p[@id="p1"]//input').send_keys("admin")

示例2:使用层级与属性结合定位策略,定位用户名输入框

//ul[@class="login_ul"]//input[@placeholder="邮箱/手机/用户名"]

**1.2.5 Xpath扩展

  • //*[text() = 'value'] value表示的是要定位的元素的全部文本内容.
    • 要定位的元素中, value表示全部文本信息
  • //*[contains(@attribute,'value')] attribute表示的属性名称, value表示的是字符串
    • 要定位的元素中, attribute属性的属性值包含了value的内容
  • //*[starts-with(@attribute,'value')] attribute表示的属性名称, value表示的是字符串
    • 要定位的元素,attribute属性的属性值是以value开头

示例1:不用 link_text 方法来定位a标签-----//*[text() = 'value'] 需要全部文本信息去定位,

<a href="http://www.sina.com.cn">新浪</a>
//*[text()='新浪']

示例2://*[contains(@attribute,'value')]

<input type="text" name="userA" id="userA" placeholder="请输入用户名">
//*[contains(@placeholder,'请输入用')]
  • 示例3://*[starts-with(@attribute,'value')]
<input type="password" name="passwordA" id="passwordA" placeholder="请输入密码">
//*[starts-with(@placeholder,'请输入密')]

或者:
//*[starts-with(@name,'pass')]

补充:当class属性有多个属性值时,用xpath定位

  • 此时class的属性要写全 写一个不行
<input type="email" name="emailA" class="emailA dzyxA" placeholder="请输入电子邮箱">
//*[@class='emailA dzyxA']

如果//*[@class='dzyxA']或者//*[@class='emailA']定位不到


2、CSS定位

2.1 什么是CSS

总结:css是可以用来在selenium中定位元素的

  • CSS定位元素的方法:
    • find_element_by_css_selector(css_selector)
    • css_selector 表示的是CSS选择器表达式

2.2 CSS定位策略

  • id选择器
  • class选择器
  • 元素选择器
  • 属性选择器
  • 层级选择器

2.2.1 id选择器

  • 表达式: #id # :表示通过元素的ID属性进行元素选择
  • id 表示的的id属性的属性值

示例:通过css的id选择器定位用户名输入框,输入admin

<input type="text" name="userA" id="userA" placeholder="请输入用户名">
driver.find_element_by_css_selector("#userA").send_keys("admin")

2.2.2 class选择器

  • 表达式: .class # . 表示通过元素的class属性进行元素选择,
  • class表示的class属性的其中一个属性值

示例:通过css的class选择器定位电子邮箱输入框,输入123@qq.com

<input type="email" name="emailA" class="emailA dzyxA" placeholder="请输入电子邮箱">
driver.find_element_by_css_selector(".emailA.dzyxA").send_keys("128217@qq.com")

2.2.3 元素选择器

  • 就是通过元素标签名称来选择元素 。表达式: tag_name 不推荐使用
  • 原因:应该相同元素的标签名太多重复,定位不准确

示例:用元素选择器 定位用户名输入框

<input type="text" name="userA" id="userA" placeholder="请输入用户名">
input

可以结合定位一组元素来精确定位  如:
示例:通过input标签定位邮箱输入框(邮箱的input标签是  页面的第四个,所以下标是3)

driver.find_elements_by_css_selector("input")[3].send_keys("123@qq.com")

2.2.4 属性选择器

  • 就是通过元素的属性来选择元素。 表达式:[attribute='value']
  • attribute 表示的是属性名称,value表示的是属性值

如果使用的是class属性,需要带上class的全部属性值

示例:通过css的属性选择器定位电子邮箱输入框,输入123@qq.com

<input type="email" name="emailA" class="emailA dzyxA" placeholder="请输入电子邮箱">
driver.find_element_by_css_selector("[class='emailA dzyxA']").send_keys("123@qq.com")

2.2.5层级选择器(重点)

  • 父子层级关系选择 器

    • 表达式: element1>element2 通过element1来找element2,

      并且element2是element1的直接子元素

    • 例如:p[id='p1']>input 通过指定的 p元素 来找 input

示例1:通过css的 父子层级关系选择器 定位用户名 输入框

用户名输入框:
<p id="pa">
    <label for="userA">账&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;号:</label>
    <input type="text" name="userA" id="userA" placeholder="请输入用户名">
</p>

电话号码输入框:
<p>
    <label for="telA">电话号码:</label>
    <input type="text" name="telA" id="telA" class="telA" placeholder="请输入电话号码">	</p>

电子邮箱输入框:
<p>
	<input type="email" name="emailA" class="emailA dzyxA" placeholder="请输入电子邮箱">		<label>电子邮箱:</label>					
</p>
p[id='pa']>input

或者结合id选择器  来结合使用
#pa>#userA

或者结合class选择器  来结合使用
定位电话号码输入框
p>.telA

或者结合属性选择器  来结合使用
定位电子邮箱输入框
p>input[name='emailA']
  • 隔代层级关系选择器
    • 表达式: element1 element2 中间有个 “空格” 通过element1来找element2,
    • 并且element2是element1的后代元素

示例:#通过css的 隔代层级选择器 定位

1,父子层级关系也可以通过  隔代层级选择器定位密码输入框 (结合id属性)
p #passwordA

2,通过div  隔代层级选择器  定位密码输入框(结合id属性)
div #passwordA

3,通过div  隔代层级选择器  定位电话号码输入框(结合class属性)
div .telA

4,通过div  隔代层级选择器  定位电子邮箱输入框(结合属性选择器)
div input[name='emailA']

补充:css各种符号的意义

#    :用来表示id属性
.    :小数点表示class属性
[]   :表示所有属性
>    :表示父子关系
空格  :用来表示祖先和子孙元素关系(层级关系)

2.2.6CSS扩展

  • input[type^='value'] input表示标签名称,type表示属性名称, value表示的文本内容
    • 查找元素type属性值是以value开头的元素
  • input[type$='value'] input表示标签名称,type表示属性名称, value表示的文本内容
    • 查找元素type属性值以value结尾的元素
  • input[type*='value'] input表示标签名称,type表示属性名称, value表示的文本内容
    • 查找元素type属性值包含value的元素

示例:定位用户名输入框

用户名输入框:
<p id="pa">
    <label for="userA">账&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;号:</label>
    <input type="text" name="userA" id="userA" placeholder="请输入用户名">
</p>
1,input[type^='value']
input[placeholder^='请输入用']

2,input[type$='value']
input[placeholder$='户名']

3,input[type*='value'] 
input[placeholder*='户']

3、元素定位总结

1.id 、name、class_name  为元素属性定位
2.tag_name    为元素标签名称定位
3.link_text  partial_link_text   为超链接定位(a标签)
4.xpath 为元素路径定位
5.css  为css选择器定位

Xpath于CSS 类似功能对比

定位方式 Xpath CSS
元素名 //input input
id //input[@id='useA'] #userA
class //*[@class='telA'] .telA
属性 1.//[text()="xxx"]
2.//
[contains(@attribute,'value')]
3.//*[starts-with(@attribute,'value')]
1.input[type^='value']
2.input[type$='value']
3.input[type*='value']
  • css比xpath写法简单,不过在时间工作中xpath用的多,因为xpath可以用下标定位(如果存在相同属性)

4、定位元素的另外一种写法(By)

  • find_element(By.ID, id) 需要导入By类。(id xpath 等要大写)
from selenium.webdriver.common.by import By

driver.find_element(By.ID,"userA").send_keys("admin")
driver.find_element(By.XPATH,"//*[@id='userA']").send_keys("admin")

三、元素操作及浏览器操作方法

1、元素操作

  • 点击操作 element.click()
    • element表示的是元素对象
  • 输入操作 element.send_keys("value")
    • element表示的是元素对象, value表示的是要输入的内容
  • 清除操作 element.clear()
    • element表示的是元素对象. 将输入框里面的内容全部清除。

示例:清除电话号码输入框的号码 18611111111 改为为:18600000000

driver.find_element_by_css_selector(".telA").send_keys("18611111111")
time.sleep(2)
driver.find_element_by_css_selector(".telA").clear()
driver.find_element_by_css_selector(".telA").send_keys("18600000000")

2、浏览器操作

浏览器常用操作方法

2.1最大化浏览器窗口

  • maximize_window()
  • 最大化浏览器窗口 --> 模拟浏览器最大化按钮 实例化浏览器驱动之后,就可以调用窗最大化的方法
driver = webdriver.Chrome()
# 窗口最大化
driver.maximize_window()

2.2设置浏览器窗口大小

  • set_window_size(width, height)
  • 设置浏览器窗口大小 --> 设置浏览器宽、高(像素点)
# 设置窗口大小
driver.set_window_size(500, 500)

2.3设置浏览器窗口位置

  • set_window_position(x, y)
  • 设置浏览器窗口位置 --> 设置浏览器位置
    • x,y是一个坐标点,通过此坐标点确定浏览器最左上角的位置,以此确定浏览器在屏幕上的位置。
    • x, y不能超过屏幕的分辨率大小
# 设置窗口位置
driver.set_window_position(300, 300)

2.4后退 ---back()

  • back()
  • 后退 --> 模拟浏览器后退按钮
# 调用浏览器的后退
time.sleep(3)
driver.back()

2.5前进 ---forward()

  • forward()

  • 前进 --> 模拟浏览器前进按钮

# 再调用浏览器的前进
time.sleep(3)
driver.forward()

2.6刷新 ---refresh()

  • refresh()
  • 刷新 --> 模拟浏览器F5刷新
#刷新浏览器
driver.refresh()

2.7关闭当前窗口 ---close()

  • close()
  • 关闭当前窗口 --> 模拟点击浏览器关闭按钮
# 再调用关闭按钮
driver.close()

2.8关闭浏览器 ---quit()

  • quit()
  • 关闭浏览器驱动对象 --> 关闭所有程序启动的窗口
# 退出
driver.quit()

2.9获取页面title

  • title
# 获取页面标题
print(driver.title)

2.10获取当前页面URL

  • current_url
# 获取页面的URL地址
print(driver.current_url)

3、获取元素信息

  • 为什么要学习获取元素信息的方法

    • 主要为了获取相关的信息进行断言,判断自动化用例最终的执行结果。
  • 获取元素常用的方法:

3.1获取元素的大小---size

  • size
  • 获取元素的大小 返回的是一个字典,里面包含 元素高度和宽度的值
  • size为属性,调用是无括号;如 xxx.size
示例:1).获取用户名输入框的大小
test=driver.find_element_by_css_selector("#userA")
print(test.size)

{'height': 45, 'width': 404}

3.2获取元素的文本内容---text

  • text
  • 获取元素的文本内容
  • text为属性,调用是无括号;如 xxx.text
# 2).获取页面上第一个超链接的文本内容
test2=driver.find_element_by_link_text("新浪")
print(test2.text)

新浪

3.3获取元素对应属性名称的属性值---get_attribute()

  • get_attribute("attribute")
  • 获取元素对应属性名称的属性值, attribute表示的是属性名
# 3).获取页面上第一个超链接的地址
test3=driver.find_element_by_link_text("新浪")
print(test3.get_attribute("href"))

http://www.sina.com.cn/

3.4判断元素是否可见

  • is_displayed()
  • 判断元素是否可见 返回值为true或者false

# 4).判断页面中的span标签是否可见
test4=driver.find_element_by_name("sp1")
print("判断元素是否可见,默认应该是False:",test4.is_displayed())
print("打印displayed的值:",test4.get_attribute("display"))

判断元素是否可见,默认应该是False: False
打印displayed的值: None

3.5判断元素是否可用

  • is_enabled()
  • 判断元素是否可用,返回值为true或者false
# 5).判断页面中取消按钮是否可用
test5=driver.find_element_by_id("cancelA")
print("判断取消按钮是否可用,默认应该是False:",test5.is_enabled())

判断取消按钮是否可用,默认应该是False: False

3.6判断复选框或单选框是否被选中

  • is_selected()
  • 判断复选框或者单选框是否被选中,返回值为true或者false
# 6).判断页面中'旅游'对应的复选框是否为选中的状态
test6=driver.find_element_by_id("lyA")
print("判断旅游复选框是否选中,默认应该是True:",test6.is_selected())


判断旅游复选框是否选中,默认应该是True: True

四、鼠标和键盘操作

1、鼠标操作

1.1 鼠标操作实现方式

  • selenium提供鼠标操作的方法及步骤

    需要导入ActionChains类

    • 通过ActionChains实例化鼠标对象 action =ActionChains(driver)

      • driver表示的是浏览器驱动对象
    • 调用鼠标的事件方法

    • 调用鼠标的执行方法 action.perform()

1.2 鼠标右击操作

  • 右击操作的实现步骤:

    针对由html自定义的右键菜单。可以使用右击的方式来进行操作。

    • 创建鼠标对象 action = ActionChains(driver)
    • 调用右击事件方法 action.context_click(element)
      • element表示的是一个元素对象

    • 调用鼠标执行方法 action.perform()
from selenium.webdriver import ActionChains

# 在用户名文本框上点击鼠标右键
# 创建鼠标对象
action = ActionChains(driver)
# 调用鼠标右击的方法
action.context_click(driver.find_element_by_id("userA"))
# 调用鼠标执行的方法
action.perform()

1.3 鼠标双击操作

  • 鼠标双击的实现步骤
    • 创建鼠标对象 action=ActionChains(driver)
    • 调用鼠标双击事件方法 action.double_click(element)
      • element表示是元素对象

    • 调用鼠标的执行方法 action.perform()
from selenium.webdriver import ActionChains

# 输入用户名admin,暂停3秒钟后,双击鼠标左键,选中admin
element = driver.find_element_by_id("userA")
element.send_keys("admin")
time.sleep(3)
# 创建鼠标对象
action = ActionChains(driver)
# 调用鼠标双击事件方法
action.double_click(element)
# 调用鼠标执行方法
action.perform()

1.4 鼠标拖动操作

  • 鼠标拖动的实现步骤:

    • 创建鼠标对象 action = ActionChains(driver)

    • 调用鼠标拖动事件方法 action.drag_and_drop(source,target)

      • source表示的是源元素,被拖动的元素, target

      • 表示是目标源,也就是要拖动到哪个元素上。

    • 调用鼠标执行方法 action.perform()

from selenium.webdriver import ActionChains
# 把红色方框拖拽到蓝色方框上

source = driver.find_element_by_id("div1")
target = driver.find_element_by_id("div2")
# 实例化鼠标对象
action = ActionChains(driver)
# 调用鼠标拖动事件方法
action.drag_and_drop(source, target)
# 调用鼠标执行方法
action.perform()

1.5 鼠标悬停操作(掌握)

  • 鼠标悬停实现步骤:
    • 实例化鼠标对象 action = ActionChains(driver)
    • 调用鼠标悬停事件方法 action.move_to_element(element)
      • element表示的是元素对象
    • 调用鼠标执行方法 action.perform()
from selenium.webdriver import ActionChains

# 模拟鼠标悬停在‘注册’按钮上
element = driver.find_element_by_css_selector("p button")
# 创建鼠标对象
action = ActionChains(driver)
# 调用鼠标悬停事件方法
action.move_to_element(element)
# 调用鼠标执行方法
action.perform()

1.6 鼠标单元素拖动操作(掌握)

  • 场景:拖动滑动快

  • 鼠标单元素拖动实现步骤

    • 创建鼠标对象 action=ActionChains(driver)
    • 调用鼠标单元素拖动事件方法
      • action.drag_and_drop_by_offset(element, x, y) x, y 表示的元素拖动时横向和纵向移动的距离,单位为像素,element表示的是元素对象 移动的像素最终要比在web页面中看到的移动像素值要大,最好大于5个像素或者10像素
    • 调用鼠标执行方法 action.perform()
    x>260    y表示纵向距离 没有移动  所以y=0
    

from selenium.webdriver import ActionChains

# 模拟鼠标实现滑块验证码的操作
element = driver.find_element_by_css_selector(".handler.handler_bg")
# 创建鼠标对象
action = ActionChains(driver)
# 调用鼠标单元素拖动事件方法
action.drag_and_drop_by_offset(element, 265, 0)
# 调用鼠标执行方法
action.perform()

2、键盘操作

  • 模拟键盘上面的快捷键的操作
  • 调用键盘操作的快捷键的方法 element.send_keys(快捷键的键值)
    • 需要导入Keys类, 第一个字母是大写
    • 单键值: 直接传入对应的键值 send_Keys("a")
    • 组合键: 键值之间由逗号分隔 send_keys(Keys.CONTROL, Keys.SHIFT, 'i')

常用的快捷键:

1. send_keys(Keys.BACK_SPACE)     删除键(BackSpace)
2. send_keys(Keys.SPACE)          空格键(Space)
3. send_keys(Keys.TAB)            制表键(Tab)
4. send_keys(Keys.ESCAPE)         回退键(Esc)
5. send_keys(Keys.ENTER)          回车键(Enter)
6. send_keys(Keys.CONTROL,'a')    全选(Ctrl+A)
7. send_keys(Keys.CONTROL,'c')    复制(Ctrl+C)
8. send_keys(Keys.CONTROL, 'v')   粘贴(Ctrl+V)
from selenium.webdriver.common.keys import Keys
from click import clear

# 1). 输入用户名:admin1,暂停2秒,删除1
element = driver.find_element_by_id("userA")
element.send_keys("admin1")
time.sleep(2)
# 删除最后一个字符串
element.send_keys(Keys.BACK_SPACE)


# 2). 全选用户名:admin,暂停2秒
element.send_keys(Keys.CONTROL, 'a')
time.sleep(2)

# 3). 复制用户名:admin,暂停2秒
element.send_keys(Keys.CONTROL, 'c')
time.sleep(2)

# 4). 粘贴到密码框
driver.find_element_by_id("passwordA").send_keys(Keys.CONTROL, 'V')

五、元素等待

什么是元素等待

  • 概念:在定位页面元素时如果未找到,会在指定时间内一直等待的过程

HTML加载需要时间,影响HTML加载的因素:

  • 服务器性能
  • 网络速度
  • 本身电脑的配置

1、隐式等待

概念:首先要等待整个页面加载完成,再去进行元素定位,如果在定位过程中找到了元素,直接返回该元素,继续后面的操作,如果在指定的时间内没有找到该元素,那么每隔0.5秒再去找,如果超过了指定时间,就会抛出NoSuchElementException的异常错误。

  • 隐式等待实现方式:
    • driver.implicitlty_wait(timeout)
    • timeout表示的是最长的等待时间 单位为S

隐式等待只需要设置一次,对所有的元素定位的方法都是有效的。

  • 示例:通过隐式等待的方式定位第一个延时框输入admin,第二个延时框输入admin2

# 隐式等待的时间,设置为5S
driver.implicitly_wait(5)

print("定位第一个的开始时间:",time.strftime("%H:%M:%S"))
#针对第一个延时框输入admin
driver.find_element_by_xpath("//div[@id='wait']/input[1]").send_keys("admin")
print("找到第一个元素的时间:",time.strftime("%H:%M:%S"))
#针对第二个延时框输入admin2
driver.find_element_by_xpath("//div[@id='wait']/input[2]").send_keys("admin2")
print("找到第二个元素的时间:",time.strftime("%H:%M:%S"))


定位第一个的开始时间: 16:33:36
找到第一个元素的时间: 16:33:40
找到第二个元素的时间: 16:33:45

思考:

问题1:第一个延时框加等4秒才能加载出来,第二个延长框要等9秒才能加载出来---为什么隐式等待设置等5秒就够了?
# 隐式等待的时间,设置为5S
driver.implicitly_wait(5)

----因为当html页面加载完成后,隐式等待就开始对所有定位元素生效了,等4s过后,其实第二个延长框已经过去5秒了
所以隐式等待的时间,设置为5S足够

问题2:隐式等待的时间改成4秒可以吗?
---实验后不行  报错了
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//div[@id='wait']/input[2]"}
                
问题3:如果把定位输入框的代码顺序换一下,时间也设置5秒可以吗          
#针对第二个延时框输入admin2
driver.find_element_by_xpath("//div[@id='wait']/input[2]").send_keys("admin2")
#针对第一个延时框输入admin
driver.find_element_by_xpath("//div[@id='wait']/input[1]").send_keys("admin")

----也报错

2、显示等待

概念:定位指定元素时,如果能找到该元素,那么就直接返回该 元素,如果找不到,那么每隔指定的时间再去定位该 元素,如果超出最长等待时间,那么就抛出TimeOutException。

  • 在selenium中把显示等待的相关方法封装在 --WebDirverWait 类中。

显示等待的实现:

1导包
from selenium.webdriver.support.wait import  WebDriverWait

2.WebDriverWait(driver, timeout,poll_frequency=0.5)
	1).driver: 指的是浏览器驱动对象
    2).timeout:表示的是最长等待时间
    3).poll_frequency:表示的是检测的间隔时间,默认是0.5
    	和后面跟上until方法,在until方法跟上匿名函数来实现元素定位。
        
        
3.调用方法  until(method):  直到...时
    1).method:函数名称 该函数用来实现对元素的定位
    2).一般使用匿名行数来实现,lambda x:x.find_element_by_id("userA")
        
4示例:
element=WebDriverWait(driver, 10,1).until(lambda x:x.find_element_by_id("userA"))
  • 示例:通过显示等待的方式定位延时输入框输入admin
from selenium.webdriver.support.wait import WebDriverWait

#针对第一个延时框输入admin
WebDriverWait(driver,9,1).until(lambda x:x.find_element_by_xpath("//div[@id='wait']/input[1]")).send_keys("admin")
  • 示例2----不使用匿名函数(弹出框)
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait

WebDriverWait(driver,30,0.5).until(expected_conditions.alert_is_present())
driver.switch_to.alert.accept()

显示等待与隐式等待的区别:

  • 1、抛出的异常不一样 , 隐式等待超时,报的NoSuchElementException ,显示等待超时,报的是

    TimeOutException

  • 2、作用域不一样, 隐式等待对所有元素定位的方法都有效,只需要定义一次, 显示等待只针对单个元素

  • 3、显示等待不需要等待整个页面的HTML的DOM树加载完成,显式等待的效率更高,工作当中一般使用显示等待。而隐式等待需整个HTML DOM树加载完成。

3、强制等待

  • 强制等待就是让代码休眠,不做任何的操作

    time.sleep(time) 单位为time

  • 常用的场景:

    • 当要获取元素的文本内容时,而元素的文本内容是需要通过后台接口请求并渲染的,此时,如果使用隐式等待或显示等待是没有办法获取到文本内容,所以需要使用强制等待
    • 当要操作的元素已经存在,但是有其他的元素需要等待且与该操作的元素有业务关联,如果使用隐式等待或显示等待对该元素进行操作的话,是没有办法进行的,也需要使用强制等待。

六、下拉选择框、弹出框、滚动条操作

1、下拉选择框操作

  • 下拉选 择实现步骤:

    1、导入Select类

    2、实例化select对象 select=Select(element)

    element对象表示的是select元素对象

    3、通过select的相关方法选择option选项

    • select.select_by_index(index) ---->参数index表示的option索 引
      • 根据option索引来定位,从0开始
    • select.select_by_value(value) --->参数value表示的是option元属中value的属性值
      • 根据option属性,value值拉来定位
    • select.select_by_visible_text(visible_text )---> 参数visible_text表示的是option的文本内容。
      • 根据option显示文本来定位

示例:

# 通过select对象的index来选择广州
# 通过select对象的value来选择上海
# 通过select对象的visible来选择深圳

#补充:用css或xpath定位上海
from selenium.webdriver.support.select import Select

element=driver.find_element_by_id("selectA")
#实例化select对象
select=Select(element)

# 通过select对象的index来选择广州
time.sleep(2)
select.select_by_index(2)

# 通过select对象的value来选择上海
time.sleep(2)
select.select_by_value("sh")
# 通过select对象的visible来选择深圳
time.sleep(2)
select.select_by_visible_text("深圳")

#补充:用css或xpath定位上海
time.sleep(2)
driver.find_element_by_css_selector("select option[value='sh']").click()

2、弹出框操作

网页中常见的弹出框有三种
	1、alert    警告框
	2、confirm  确认框
	3、prompt   提示框
  • 弹出框处理步骤:
    • driver.switch_to.alert 获取弹出框对象
    • 处理弹出框
      • alert.text 获取弹出框提示信息
      • alert.accept() 确定弹出框
      • alert.dismiss() 取消弹出框

示例:

1)、点击 alert 按钮
2)、关闭警告框
3)、输入用户名:admin
#1)、点击 alert 按钮
driver.find_element_by_id("alerta").click()
time.sleep(3)

#2)、# 获取弹出框
alert=driver.switch_to.alert
# 打印信息,然后取消
print(alert.text)
alert.dismiss()

# 在用户名输入框中输入admin
driver.find_element_by_id("userA").send_keys("admin")

或者配合显示等待使用:

#处理弹出框
WebDriverWait(driver,30,0.5).until(expected_conditions.alert_is_present())
driver.switch_to.alert.accept()
#12 ,点击提交按钮
driver.find_element_by_class_name("button_search").click()

3、滚动条操作

  • 滚动实现步骤:

    selenium中并没有直接提过操作滚动条的方法,但是他提供了可执行JavaScript脚本的方法,所以我们可以通过JavaScript脚本来达到操作滚动条的目的

    • 1、定义js
      • js = "window.scrollTo(0, 2000)"
      • 如果想要移动到最下方,y值给最大值就可以了。
    • 2、执行JS
      • driver.execute_script(js)

示例:打开注册页面A,暂停2秒后,滚动条拉到最底层

time.sleep(2)
# 控制滚动条到最下方
# 1、定义js
js = "window.scrollTo(0, 2000)"
# 2、执行JS
driver.execute_script(js)

七、frame切换、多窗口切换

1、frame切换

  • frame:HTML页面中的一种框架,主要作用是在当前页面中指定区域显示一面元素
形式一:(了解)
<frameset cols="25%,75%">
	<frame src="./html/注册A.html" />
	<frame src="./html/注册B.html" />
</frameset>

形式二:
<iframe name="iframe_a" src="demo_iframe.htm" width="200" height="200"></iframe>

  • frame切换实现方法:
    • driver.switch_to.frame(frame_reference) --> 切换到指定frame的方法
      • frame_reference:可以为frame框架的name、id或者定位到的frame元素
    • driver.switch_to.default_content() --> 恢复默认页面方法

frame切换原理总结:

  • 针对同一层级的frame,如果要进行切换的话,需要切回到默认首页
  • 针对所要进入的frame, 有多少个层级,就需要切换几次
  • 不管当前在哪个层级,如果要回到默认首页,只需要调用一次
  • 回到默认首页的方法(driver.switch_to.default_content())

针对同级别的frame切换,要先回到默认首页面。如上图:如frame3到frame4  就不需要回到首页

如果在frame4 里,怎么切回来?---只需要回退一次就行了

示例:

#针对主页的用户名输入admin
driver.find_element_by_id("userA").send_keys("admin")

#针对 “注册用户A” 页面输入用户名adminA
#切换到指定frame
driver.switch_to.frame(driver.find_element_by_id("idframe1"))
driver.find_element_by_id("AuserA").send_keys("adminA")

# 回到默认首页面
driver.switch_to.default_content()

#针对 “注册用户B” 页面输入用户名adminB
#切换到指定frame
ele_frame=driver.find_element_by_id("idframe2")
driver.switch_to.frame(ele_frame)
driver.find_element_by_id("BuserA").send_keys("adminB")

# 回到默认首页面
driver.switch_to.default_content()

补充:怎么判断页面有没有frame ?

  • -----页面点击检查,点击“boby"观察高亮部分有没有填满整个页面,如果没有 那就存在frame

2、多窗口切换

  • 在selenium中封装了获取当前窗口句柄,获取所有窗口句柄 和切换到指定句柄窗口的方法。

    句柄:英文handle 窗口的唯一识别码

  • 窗口操作的三种方法

    • 获取当前窗口句柄: driver.current_window_handle
    • 获取所有窗口句柄: driver.window_handles 返回的是一个列表
    • 切换窗口句柄: driver.switch_to.window(window_handle)
      • window_handle表示的是要切换到哪个窗口句柄

窗口句柄:由操作系统生成的一串唯 一识别码,是一串字符。

# 在注册实例页面中点击 注册A页面
driver.find_element_by_id("ZCA").click()

time.sleep(1)
# 获取当前窗口句柄信息
print(driver.current_window_handle)

# 获取所有窗口句柄
windows = driver.window_handles
print(windows)

# 切换窗口句柄
driver.switch_to.window(windows[-1])

# 在注册A页中输入用户名和密码
driver.find_element_by_id("userA").send_keys("admin")
driver.find_element_by_id("passwordA").send_keys("123456")


CDwindow-072180038550560AA0D7551C27B8ABFC
['CDwindow-072180038550560AA0D7551C27B8ABFC', 'CDwindow7D0B508DB9685FCCAB5AB60618F8CD97']

窗口切换与frame切换的区别:

  • 窗口切换是指针对浏览器窗口, frame切换针对的是同一个窗口中的html代码。

八、窗口截图、验证码处理

1、窗口截图

思考:如果自动化脚本运行时出现了异常,该如何处理?

-------截图

  • 目的:当程序运行出错时,通过截图文件能够更直观的知道具体是哪个操作步骤出错

  • 窗口截图就是指把出错的图片保存到指定位置。

    载图方法: driver.get_screenshot_as_file(filename)

    • 截图的文件名必须是以PNG结尾
    • filename中的文件目录必须手动创建
需求:
示例:输入密码---故意定位不到密码框,模拟代码报错--然后截图保存
关联技术:用到捕获异常  
try:
    xxx
except Exception as  e:
    driver.get_screenshot_as_file()
    #抛出异常
    raise e
    
try:
    #输入用户名
    driver.find_element_by_id("userA").send_keys("admin")
    #输入密码---故意定位不到密码框,模拟代码报错
    driver.find_element_by_id("padd").send_keys("1234")
except Exception as  e:
    driver.get_screenshot_as_file("error.png")
    # 打印异常信息
    print(e)
    #或抛出异常
    raise e

2、验证码处理

2.1 什么是验证码?

验证码就是指一种随机生成的信息(数字、字母、汉字、图片、算术题)等为了防止恶意的请求行为,增加应用的

安全性。

自动化过程中也是需要进行注册或者登陆的操作,所以需要处理验证码。

2.2 验证码处理方式

  • 去掉验证码 ----------由开发操作 , 用在测试环境
  • 设置万能验证码 --------由开发 操作, 一般也只使用在测试环境,
  • 验证码识别技术 ------由于技术难度高(python-tesseract),识别率很难达到100%,一般不建议使用
  • 记录cookie ---------通过记录cookie来跳过登陆的操作。

2.3 Cookie原理

原理:

  • Cookie是由Web服务器生成的,并且保存在用户浏览器上的小文本文件,它可以包含用户相关的信息。
  • Cookie数据格式:键值对组成(python中的字典)
  • Cookie产生:客户端请求服务器,如果服务器需要记录该用户状态,就向客户端浏览器颁发一个Cookie数据
  • Cookie使用:当浏览器再次请求该网站时,浏览器把请求的数据和Cookie数据一同提交给服务器,服务器检查该Cookie,以此来辨认用户状态。

2.4 selenium操作cookie(重点)

  • driver.get_cookie(name) 获取指名称的cookie信息 返回的是一个字典
  • driver.get_cookies() 获取的是所有cookie的信息, 返回的是一个列表
  • driver.add_cookie(dict_cookie) 往浏览器驱动增加cookie,dict_cookie是一字典

注意事项:如何确认哪个cookie是用来控制用户权限的

  • 可以问开发同学
  • 针对登陆的前后的cookie进行对比,比登陆之前多的cookie都可以用来使用控制用户权限。
  • 手动登陆之后不能退出,退出之后就相当于cookie无效了。

案例1:

需求案例: selenium操作cookie
使用cookie实现登录tpshop
driver.get("http://127.0.0.1/Home/user/login.html")

#手动登录获取登录之后的cookie信息 
cookie={"name":"PHPSESSID",
        "value":"nmh4jjt15db2smsmka0vl2th70"
    }

#在浏览器中添加cookie
driver.add_cookie(cookie)

#页面刷新
driver.refresh()

案例2

需求案例: selenium操作cookie
使用cookie实现登录海盗商城
登录接口:http://127.0.0.1/index.php?m=user&c=public&a=login
首页接口:http://127.0.0.1/index.php

思路1:可以问开发,,确定那个cookie是用来控制登录权限的
思路2:针对登录的前后cookie进行对比,比登录之前多的cookie都可以用来使用控制用户权限

思路:登录前看下有哪些cookie

登录后看下cookie

把登录后的cookie都加进去

driver.get("http://127.0.0.1/index.php?m=user&c=public&a=login")

#手动登录获取登录之后的cookie信息
cookie={"name":"_uname","value":"mike111"}
#在浏览器中添加cookie
driver.add_cookie(cookie)

cookie={"name":"PHPSESSID","value":"lej1kvfer57s6fr765kc8kc8f3"}
driver.add_cookie(cookie)


cookie={"name":"user_key","value":"408egzv1xY8S3xBpROYIX%2FGr8oSX%2BoTlkWqWIq64qA"}
driver.add_cookie(cookie)

cookie={"name":"cart_num","value":"1"}
driver.add_cookie(cookie)

driver.get("http://127.0.0.1/index.php")

九、扩展知识点

1.解决注册用例可重复执行的问题?

3种解决方案:

  • 通过python代码编写一个生成手机号码的函数 (会生成比较多的垃圾数据)
  • 在注册之前,备份一处数据库(备份只需要做一次),执行注册的用例,每次执先完用例之后,再去恢复数据库(如果数据库数据量大,那么恢复的时间会比较久,效率比较低)
  • 通过python脚本直接在数据库删除新注的用户(要熟悉底层的数据库业务,要知道注册用户是存在哪些表中)

示例:通过python代码编写一个生成手机号码的函数

import time
import random
from selenium import  webdriver

driver=webdriver.Chrome()
driver.maximize_window()

#定义获取手机号码的函数名
def get_mobile():
    # 确定手机号码所需要格式
    mobiles=['130','131','134','135']
    # 通过时间戳获取手机号码的后8位数(一定不会重复)
    number = str(int(time.time()))[2:]
    # 把手机号码格式的三位数与后8位数相加
    mobile=random.choice(mobiles)+number
    return mobile

driver.get("http://127.0.0.1/index.php/Home/user/reg.html")

driver.find_element_by_id("username").send_keys(get_mobile())
driver.find_element_by_name("verify_code").send_keys("8888")
driver.find_element_by_id("password").send_keys("123456")
driver.find_element_by_id("password2").send_keys("123456")
driver.find_element_by_css_selector(".regbtn.J_btn_agree").click()

time.sleep(3)
driver.quit()

2、文件上传

方法1:

  • 我们在web页面实现文件上传过程中,可以直接把文件在磁盘完整路径,通过sendKeys方法实现上传
#如何上传文件?
# 在前端点击的按钮不是真正负责上传文件的控件    真正负责上传文件的控件是   <input type="file">
# 我门要做的是 找到这个控件   然后  直接对这个 控件进行send_keys,发送图片路径即可

<input type="file" name="upfilea">
driver.find_element_by_name("upfilea").send_keys("D:/5a754b97e631c.jpg")

方法2:

第三方工具叫autoIT

  • 安装 这个工具。autoit V3工具是用来查

    看windows窗口信息及控件信息的

  • 安装pyautoit模块。

    • 解压pyautoit-master.zip文件
    • 在windows窗口进入到解压目录之后,再在地址栏输入cmd
    • 执行以下命令 python setup.py install
import time
import autoit
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(10)
driver.get("http://www.baidu.com")

# 点击百度上面的照相机按钮
driver.find_element(By.CSS_SELECTOR, ".soutubtn").click()
# 点击选择文件
ele = driver.find_element(By.CSS_SELECTOR, ".uploadpic")
# 定义鼠标对象
action = ActionChains(driver)
# 调用鼠标事件
action.click(ele)
# 执行鼠标事件方法
action.perform()
time.sleep(2)

# 针对windows操作
# 通过autoit来获取弹出的窗口
autoit.win_wait_active("打开", 3)  # 3表示的是时间,秒为单位
# 在文件选择输入框中输入文件的地址及文件名称
autoit.control_send("打开", "Edit1",r"C:\Users\LiaoFei\Pictures\Saved Pictures\333.jpg")
# 在弹出窗口中点击打开按钮
autoit.control_click("打开", "Button1")
time.sleep(10)
driver.quit()

3.日历控件

#如何操作日历控件?
传统的办法:是一次一次的点击  选择年月日
新方法:
1,删除readonly属性
2,直接向日历控件中输入日期(selenium不能删除一个元素的属性 但是javascript可以)


<input type="text" id="date" name="birthday" class="input_2" readonly="" value="1970-01-01" nullmsg="请输入选择日期!">

input:表示输入框
text:表示文本输入框
readonly:只读,不允许输入


document.getElementById("date").removeAttribute("readonly")
import time
from selenium import webdriver

driver=webdriver.Chrome()
driver.implicitly_wait(10)
driver.maximize_window()
driver.get("http://192.168.1.3/index.php?m=user&c=public&a=login")
driver.find_element_by_id("username").send_keys("Mike")
driver.find_element_by_id("password").send_keys("123456")
driver.find_element_by_id("password").submit()

#2,点击“账号设置”
driver.find_element_by_link_text("账号设置").click()
#3.点击“个人资料”
driver.find_element_by_partial_link_text("人资").click()

#输入生日
#删除readonly属性
script='document.getElementById("date").removeAttribute("readonly")'
driver.execute_script(script)
#清除默认值:1970-01-01
driver.find_element_by_id("date").clear()
#在生日输入框中 输入新的生日
driver.find_element_by_id("date").send_keys("2022-07-08")

补充:js的5种定位方式

1)id定位: document.getElementById()

2)name定位:document.getElementByName()

3)tag定位:document.getElementByTagName()

4)class定位:document.getElementByClassName()

5)css定位:document.querySelectorAll()

posted @ 2022-08-25 19:39  mike002  阅读(245)  评论(0)    收藏  举报