一、认识Web自动化
首先看一下ChatGPT的解答:
Web 自动化测试涉及多个方面的知识和技能,包括以下内容:
-
编程语言:通常使用 Python、Java、JavaScript 等编程语言进行自动化测试脚本的编写。掌握至少一种编程语言是必要的。
-
Web 开发技术:了解 HTML、CSS、JavaScript 等基本的 Web 开发技术,有助于理解 Web 页面的结构和交互。
-
自动化测试框架:掌握一种或多种适用于 Web 自动化测试的测试框架,如Selenium、WebDriverIO、Cypress等。这些框架提供了丰富的 API 和功能,方便操作浏览器,模拟用户行为,以及验证页面内容。
-
页面元素定位:学习如何使用选择器(CSS 选择器、XPath 等)准确地定位 Web 页面上的元素,以便对其进行操作和验证。
-
操作浏览器:了解如何使用自动化测试框架控制浏览器的行为,包括打开、关闭浏览器,导航到指定 URL,模拟用户输入和点击等。
-
断言和验证:学习如何编写断言来验证页面上的内容和元素状态,确保页面的行为符合预期。
-
测试数据管理:掌握如何管理测试数据,包括准备测试数据、清理测试数据等,以确保测试的独立性和可重复性。
- 持续集成与持续部署:了解如何将 Web 自动化测试集成到持续集成(CI)和持续部署(CD)流程中,以便自动化执行测试并及时反馈测试结果。
应用场景:
解决重复性操作的问题
-
解决-回归测试
-
解决-压力测试
-
解决-兼容性测试
正确认识:
-
优点
-
较少的时间内运行更多的测试用例
-
自动化脚本可以重复运行
-
减少人为错误
-
克服手工测试的局限性
-
-
误区
-
自动化测试可以完全代替手工测试
-
自动化测试一定比手工测试厉害
-
自动化测试可以发现更多bug
-
自动化测试适用于所有功能
-
分类:
-
接口-自动化测试
-
web-自动化测试(本阶段学习)
-
移动-自动化测试
-
单元-自动化测试(一般是开发人员进行的)
什么样的项目适合做web自动化测试?
-
需求变动不频繁
-
项目周期长
-
项目需要回归测试
web自动化测试什么时候开始?
手工测试结束后
web自动化测试所属的分类
属于功能测试(黑盒)
主流工具:
-
QTP
-
selenium
-
robot framework
selenium特点:
-
开源: 开放源代码
-
跨平台: linux, windows, mac
-
支持多种浏览器: Chrome, Firefox, IE, Edge, Opera, Safari等
-
支持多种语言: python, java, C#, JS, ruby, PHP等
-
成熟稳定: 被很多500强所使用
-
功能强大
二、Selenium环境搭建
基于python搭建环境:
-
python 开发环境 (python v3.x)
-
安装selenium包
# 安装 pip install selenium # 验证 pip list # 卸载 pip uninstall selenium
3. 安装浏览器(推荐安装 Chrome浏览器)
4. 安装浏览器驱动 WebDriver
1. 下载浏览器驱动(谷歌浏览器驱动) 地址: https://npm.taobao.org/mirrors/chromedriver/ > 谷歌浏览器下载地址: https://www.chromedownloads.net/ 2. 把驱动文件所在目录添加到 Path 环境变量中 > 或者直接放到python安装目录, 因为python的安装目录已经添加到了Path中
测试是否成功:
# 需求: 通过程序, 启动浏览器, 并打开百度首页, 暂停3秒, 关闭浏览器 # 1.导包 import time from selenium import webdriver # 2.创建浏览器驱动对象 driver = webdriver.Chrome() # 3.打开百度首页 driver.get("http://www.baidu.com") # 4.暂停3秒 time.sleep(3) # 5.关闭驱动对象 driver.quit()
三、Selenium-元素定位
元素定位就是通过元素的信息或元素的层级结构来定位元素
在 Selenium 中,常用的八种元素定位方式包括:
ID 定位:使用元素的唯一标识符 ID 进行定位。 driver.find_element_by_id("element_id")
类名定位:使用元素的类名进行定位。 driver.find_element_by_class_name("class_name")
标签名定位:使用元素的标签名进行定位,通常用于一组相似的元素。 driver.find_element_by_tag_name("tag_name")
名称定位:使用元素的名称属性进行定位,通常用于表单元素。 driver.find_element_by_name("name_attribute")
链接文本定位:使用链接文本进行定位,适用于链接元素。 driver.find_element_by_link_text("link_text")
部分链接文本定位:使用部分链接文本进行定位,匹配部分链接文本。 driver.find_element_by_partial_link_text("partial_link_text")
CSS 选择器:使用 CSS 选择器进行定位,提供了灵活和强大的定位能力。 driver.find_element_by_css_selector("css_selector")
XPath:使用 XPath 进行定位,提供了更复杂和灵活的定位方式。 driver.find_element_by_xpath("xpath_expression")
这些定位方法都可以用于定位单个元素。如果需要定位多个元素,可以将 find_element_by_ 替换为 find_elements_by_ 并使用相同的定位方法。
# 1.导包 import time from selenium import webdriver # 2.创建浏览器驱动对象 driver = webdriver.Chrome() # 3.业务操作 driver.get("file:///C:/Users/57769/Desktop/pagetest/%E6%B3%A8%E5%86%8CA.html") driver.find_element_by_id("userA").send_keys("admin") driver.find_element_by_id("passwordA").send_keys("123456") # 4.暂停3秒 time.sleep(5) # 5.关闭驱动对象 driver.quit()
# 1.导包 import time from selenium import webdriver # 2.创建浏览器驱动对象 driver = webdriver.Chrome() # 3.业务操作 driver.get("file:///C:/Users/57769/Desktop/pagetest/%E6%B3%A8%E5%86%8CA.html") driver.find_element_by_link_text("访问 新浪 网站").click() # 4.暂停5秒 time.sleep(5) # 5.关闭驱动对象 driver.quit()
定位一组元素:
elements = driver.find_elements_by_xxx("xxxxxx")
作用:
1. 查找定位符合条件的所有元素
2. 返回值是一个列表
说明: 列表数据格式的读取需要指定下标(下标从0开始)
案例:
打开 注册A.html 页面, 完成以下操作
1. 使用 tag_name 定位密码输入框(第二个input标签), 并输入123456
2. 5秒后关闭浏览器
# 1.导包 import time from selenium import webdriver # 2.创建浏览器驱动对象 driver = webdriver.Chrome() # 3.业务操作 driver.get("file:///C:/Users/57769/Desktop/pagetest/%E6%B3%A8%E5%86%8CA.html") elements = driver.find_elements_by_tag_name("input") elements[1].send_keys("123456") # 4.暂停5秒 time.sleep(5) # 5.关闭驱动对象 driver.quit()
为什么要学习XPath/CSS定位?
1.如果要定位的元素没有 id, name, class...属性, 该如何进行定位?
2.如果通过 name, class, tag_name...无法定位到唯一的元素, 该如何进行定位?
示例:
<input type="submit value="提交" / >
(一)XPath:
四种定位方式
-
路径
-
利用元素属性
-
属性与逻辑结合
-
层级与逻辑结合
1、路径:
绝对路径: 从最外层元素到指定元素所经过的所有元素层级的路径
绝对路径以 /html 为开始, 使用 / 来分割元素层级
如: /html/body/div/fieldset/p[1]/input
不建议使用
相对路径: 匹配任意层级的元素, 不限制元素的位置
相对路径以 // 开始
格式: //input 或者 //*
需求: 打开 注册A.html 页面, 完成以下操作: 1.使用绝对路径定位用户名输入框, 并输入 admin 2.暂停 3s 3.使用相对路径定位密码输入框, 并输入 123 import time from selenium import webdriver driver = webdriver.Chrome() driver.get("file:///C:/Users/57769/Desktop/pagetest/%E6%B3%A8%E5%86%8CA.html") # 定位用户名输入框, 输入 admin driver.find_element_by_xpath("/html/body/div/fieldset/form/p[1]/input").send_keys("admin") # 暂停3s time.sleep(3) # 定位密码输入框, 输入 123 driver.find_element_by_xpath("//*[@id='passwordA']").send_keys("123") time.sleep(5) driver.close()
使用谷歌浏览器获取 XPath 表达式的过程:
-
元素上右键 -> 检查
-
在F12对应的文档中的对应元素上 右键 -> Copy -> Copy XPath 或者 Copy full XPath
//*[@id='passwordA']
是一个 XPath 表达式,用于定位具有 id 属性为 "passwordA" 的任何元素。让我们来分解这个表达式://
表示从文档的根节点开始搜索。*
表示选择任何元素。[@id='passwordA']
表示选择具有 id 属性值为 "passwordA" 的元素。
2、利用元素属性
说明: 通过使用元素的属性信息来定位元素
格式: //input[@id='userA'] 或者 //*[@id='userA']
import time from selenium import webdriver driver = webdriver.Chrome() driver.get("file:///C:/Users/57769/Desktop/pagetest/%E6%B3%A8%E5%86%8CA.html") # 利用元素属性通过XPath 定位用户名输入框, 并输入 admin # driver.find_element_by_xpath("//*[@name='userA']").send_keys("admin") # driver.find_element_by_xpath("//*[@id='userA']").send_keys("admin") # driver.find_element_by_xpath("//*[@placeholder='请输入用户名']").send_keys("admin") driver.find_element_by_xpath("//*[@type='text']").send_keys("admin") time.sleep(5) driver.close()
3、属性与逻辑相结合
说明: 解决元素之间存在相同属性值的问题
格式: //*[@name='xxx' and @class='yyy']
import time from selenium import webdriver driver = webdriver.Chrome() # 打开A页面完成以下操作 # 使用属性和逻辑结合的定位策略, 在密码输入框里输入: 123 driver.get("file:///C:/Users/57769/Desktop/pagetest/%E6%B3%A8%E5%86%8CA.html") driver.find_element_by_xpath("//*[@type='password' and @name='passwordA']").send_keys("123") time.sleep(5) driver.close()
4、属性与层级相结合
说明: 如果通过元素自身的属性不方便直接定位该元素, 则可以先定位到其父元素, 然后再找到该元素
格式: //*[@id='p1']/input
import time from selenium import webdriver driver = webdriver.Chrome() # 打开A页面完成以下操作 # 使用层级与属性结合的定位策略, 在test1对应的输入框里输入: test1 driver.get("file:///C:/Users/57769/Desktop/pagetest/%E6%B3%A8%E5%86%8CA.html") driver.find_element_by_xpath("//*[@id='p1']/input").send_keys("test1") time.sleep(5) driver.close()
5、XPath扩展
说明: 不使用函数时: //*[@id='xxx'] 使用函数后 //*[text()='xxx'] 文本内容是 xxx 的元素 //*[contains(@attribute, 'xxx')] 属性中含有 xxx 值的元素 //*[starts-with(@attribute, 'xxx')] 属性以xxx开头的元素
import time from selenium import webdriver driver = webdriver.Chrome() driver.get("file:///C:/Users/57769/Desktop/pagetest/%E6%B3%A8%E5%86%8CA.html") # driver.find_element_by_xpath("//*[text()='访问 新浪 网站']").click() # driver.find_element_by_xpath("//*[contains(@placeholder, '用户名')]").send_keys("admin") driver.find_element_by_xpath("//*[starts-with(@placeholder, '请输入密')]").send_keys("1234") time.sleep(5) driver.close()
(二)CSS:
常用的定位方式 element = driver.find_element_by_css_selector(css表达式)
-
id选择器
-
class选择器
-
元素选择器
-
属性选择器
-
层级选择器
1、id选择器
例如: #userA (选择id属性值为userA的元素)
import time from selenium import webdriver driver = webdriver.Chrome() # 需求: 打开A页面, 使用CSS定位方式中的id选择器, 定位用户名输入框, 并输入 admin driver.get("file:///C:/Users/57769/Desktop/pagetest/%E6%B3%A8%E5%86%8CA.html") driver.find_element_by_css_selector("#userA").send_keys("admin") time.sleep(5) driver.close()
2、class选择器
例如: .telA (选择class属性值为 telA的元素)
# 需求: 打开A页面, 使用CSS定位方式中的class选择器, 定位电话号码输入框, 并输入 13100000000 driver.get("file:///C:/Users/57769/Desktop/pagetest/%E6%B3%A8%E5%86%8CA.html") driver.find_element_by_css_selector(".telA").send_keys("13100000000")
3、元素选择器
例如: input (选择input元素)
# 需求: 打开A页面, 使用CSS定位方式中的元素选择器, 定位注册按钮, 并点击 driver.get("file:///C:/Users/57769/Desktop/pagetest/%E6%B3%A8%E5%86%8CA.html") driver.find_element_by_css_selector("button").click()
4、属性选择器
格式: [attribute=value]
例如: [type='password'] (选择 type 属性值为 password 的元素)
# 需求: 打开A页面, 使用CSS定位方式中的属性选择器, 定位密码输入框, 并输入 123456 driver.get("file:///C:/Users/57769/Desktop/pagetest/%E6%B3%A8%E5%86%8CA.html") driver.find_element_by_css_selector("[type='password']").send_keys("123456")
5、层级选择器
说明: 根据元素的父子关系来选择 格式1: element1>element2 通过element1来定位element2, 并且 element2 必须为 element1 的直接子元素 例如1: p[id='p1']>input (定位指定p元素下的直接子元素input) 格式2: element1 element2 通过element1来定位element2, 并且 element2 为 element1的后代元素 例如2: p[id='p1'] input (定位指定p元素下的后代元素 input)
# 需求: 打开A页面, 使用CSS定位方式中的层级选择器, 定位用户名输入框, 并输入 admin driver.get("file:///C:/Users/57769/Desktop/pagetest/%E6%B3%A8%E5%86%8CA.html") # driver.find_element_by_css_selector("p[id='pa']>input").send_keys("admin") driver.find_element_by_css_selector("div[class='zc'] input").send_keys("admin")
6、CSS扩展
input[type^='p'] type属性以p字母开头的元素 input[type$='d'] type属性以d字母结束的元素 input[type*='w'] type属性包含w字母的元素
# 需求: 打开A页面, 使用CSS定位扩展的方式, 定位用户名输入框, 并输入 admin driver.get("file:///C:/Users/57769/Desktop/pagetest/%E6%B3%A8%E5%86%8CA.html") # driver.find_element_by_css_selector("input[type^='t']").send_keys("admin") # driver.find_element_by_css_selector("input[name^='u']").send_keys("admin") # driver.find_element_by_css_selector("input[type$='t']").send_keys("admin") driver.find_element_by_css_selector("input[type*='ex']").send_keys("admin")
XPath和CSS对比:
-
通过标签名定位:
- XPath:
//input
- CSS:
input
这两者都是通过标签名来定位元素,XPath 使用了双斜杠
//
表示从文档中选择所有匹配的元素,而 CSS 则直接使用标签名来选择。 - XPath:
-
通过id属性定位:
- XPath:
//*[@id='userA']
- CSS:
#userA
在XPath中,通过在方括号内使用
@id='userA'
来匹配具有id属性为'userA'的任何元素。而在CSS中,通过#userA
直接指定id属性为'userA'的元素。 - XPath:
-
通过class属性定位:
- XPath:
//*[@class='telA']
- CSS:
.telA
通过class属性定位元素时,XPath 中使用
@class='telA'
来匹配具有class属性为'telA'的任何元素,而 CSS 中直接使用.telA
来匹配类名为 'telA' 的元素。 - XPath:
-
通过其他属性定位:
- XPath:
//*[starts-with(@type,'x')]
:以x字母开头的type值的元素//*[contains(@type, 'x')]
:包含x字母的type值的元素//*[text()='x']
:文本内容为 x 的元素
- CSS:
[type^='x']
:以x字母开头的type值的元素[type*='x']
:包含x字母的type值的元素[type$='x']
:以x字母结尾的type值的元素
在XPath中,可以使用
starts-with()
和contains()
函数来匹配属性值的开头或包含指定字符串的元素,也可以使用text()
函数来匹配具有指定文本内容的元素。而在CSS中,使用了属性选择器,^
表示以指定字符串开头,*
表示包含指定字符串,$
表示以指定字符串结尾。 - XPath:
另一种写法:
方法: driver.find_element(方式, 值)
备注:
1.需要2个参数, 第1个参数为定位的类型(由By提供), 第2个参数传入具体的值
2.如果要使用By, 需要导包
# 八中定位方法都适用"另一种方法" # driver.find_element(By.ID, "userA").send_keys("admin") driver.find_element(By.XPATH, "//*[@placeholder='请输入电子邮箱']").send_keys("[email protected]")
四、元素操作
需求:打开注册A页面,完成以下操作 1.通过脚本执行输入用户名:admin;密码:123456;电话号码:18611111111;电子邮件:[email protected] 2.间隔3秒,修改电话号码为:18600000000 3.间隔3秒,点击‘注册’按钮 4.间隔3秒,关闭浏览器 ps: 元素定位方法不限
import time from selenium import webdriver from selenium.webdriver.common.by import By driver = webdriver.Chrome() # 打开注册A页面,完成以下操作 # 1.通过脚本执行输入用户名:admin;密码:123456;电话号码:18611111111;电子邮件:[email protected] # 2.间隔3秒,修改电话号码为:18600000000 # 3.间隔3秒,点击‘注册’按钮 # 4.间隔3秒,关闭浏览器 # ps: 元素定位方法不限 driver.get("file:///C:/Users/57769/Desktop/pagetest/%E6%B3%A8%E5%86%8CA.html") # 1 driver.find_element_by_id("userA").send_keys("admin") driver.find_element_by_id("passwordA").send_keys("123456") driver.find_element_by_id("telA").send_keys("18611111111") driver.find_element_by_name("emailA").send_keys("[email protected]") # 2 time.sleep(3) driver.find_element_by_id("telA").clear() driver.find_element_by_id("telA").send_keys("18600000000") # 3 time.sleep(3) driver.find_element_by_css_selector("body > div > fieldset > form > p:nth-child(5) > button").click() # 4 time.sleep(3) driver.close()
五、浏览器操作
import time from selenium import webdriver driver = webdriver.Chrome() driver.get("file:///C:/Users/57769/Desktop/pagetest/%E6%B3%A8%E5%86%8CA.html") ## maximize_window() 浏览器窗口最大化 # driver.maximize_window() ## set_window_size() 设置窗口大小(单位:像素点) set_window_position() 设置窗口的位置 # driver.set_window_size(300, 300) # driver.set_window_position(300, 300) ## back() 后退 forward() 前进 refresh() 刷新 # driver.back() # driver.forward() # time.sleep(3) # driver.refresh() ## title 获取页面标题 current_url 获取当前页面url # print("页面标题:", driver.title) # print("当前页面地址:", driver.current_url) ## driver.close() 关闭当前浏览器窗口 ==> 执行结果, 留下了新浪网站, 关闭了注册A页面 # time.sleep(3) # driver.find_element_by_link_text("访问 新浪 网站").click() # time.sleep(3) # driver.close() ### 序号 30~48 的脚本应该使用 driver.quit() 关闭浏览器驱动 而不是 driver.close() ## driver.quit() 关闭浏览器驱动对象(关闭浏览器) ==> 执行结果, 关闭所有窗口, 关闭浏览器驱动 time.sleep(3) driver.find_element_by_link_text("访问 新浪 网站").click() time.sleep(3) driver.quit()
六、获取元素信息
size 返回元素大小
text 获取元素文本
get_attribute("xxx") 获取属性值, 参数是元素的属性名
is_displayed() 判断元素是否可见
is_enabled() 判断元素是否可用
is_selected() 判断元素是否选中, 用来检查复选框或单选按钮
# 需求: 打开A页面, 完成以下操作: # 1.获取用户名输入框的大小 print(driver.find_element_by_id("userA").size) # 2.获取页面上第一个超链接的文本内容 print(driver.find_element_by_tag_name("a").text) # 3.获取页面上第一个超链接的地址 print(driver.find_element_by_tag_name("a").get_attribute("href")) # 4.判断页面中的span标签是否可见 print(driver.find_element_by_tag_name("span").is_displayed()) # 5.判断页面中的取消按钮是否可用 print(driver.find_element_by_id("cancelA").is_enabled()) # 6.判断页面中的'旅游'对应的复选框是否为选中状态 print(driver.find_element_by_id("lyA").is_selected())
七、鼠标操作
说明: 在Selenium中将鼠标操作的方法封装在 ActionChains 类中 实例化对象: action = ActionChains(driver) 方法: 1. context_click(element) 右击 2. double_click(element) 双击 3. move_to_element(element) 悬停 4. drag_and_drop(source, target) 拖拽 5. perform() 执行 为了更好的学习其他的方法, 我们先学习 perform() 执行方法, 因为ActionChains所有的方法都需要执行才能生效
说明: 在 ActionChains 类中所有提供的鼠标事件方法, 在调用的时候, 所有行为都存储在 ActionChains 对象中, 而 perform() 方法就是真正去执行所有的鼠标事件 强调: 必须调用 perform() 方法才能执行鼠标事件
import time from selenium import webdriver from selenium.webdriver import ActionChains driver = webdriver.Chrome() # 需求: 打开A页面, 在用户名文本框上点击鼠标右键 driver.get("file:///C:/Users/57769/Desktop/pagetest/%E6%B3%A8%E5%86%8CA.html") # 定位用户名输入框 element = driver.find_element_by_id("userA") # 执行右键点击操作 action = ActionChains(driver) action.context_click(element).perform() time.sleep(3) driver.quit()
import time from selenium import webdriver from selenium.webdriver import ActionChains driver = webdriver.Chrome() # 需求: 打开A页面, 模拟鼠标悬停在 注册 按钮上 driver.get("file:///C:/Users/57769/Desktop/pagetest/%E6%B3%A8%E5%86%8CA.html") element = driver.find_element_by_tag_name("button") action = ActionChains(driver) action.move_to_element(element).perform() time.sleep(3) driver.quit()
import time from selenium import webdriver from selenium.webdriver import ActionChains driver = webdriver.Chrome() # 需求: 打开 drag.html 页面, 把红色方框拖动到蓝色方框上 driver.get("file:///C:/Users/57769/Desktop/pagetest/drag.html") red = driver.find_element_by_id("div1") blue = driver.find_element_by_id("div2") ActionChains(driver).drag_and_drop(red, blue).perform() time.sleep(3) driver.quit()
八、键盘操作
导包 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) 提示: 以上方法很多, 不会逐一讲解, 因为调用方法都一样
import time from selenium import webdriver from selenium.webdriver.common.keys import Keys driver = webdriver.Chrome() driver.get("file:///C:/Users/57769/Desktop/pagetest/%E6%B3%A8%E5%86%8CA.html") # 1. 输入用户名 admin1, 暂停2s, 删除1 element = driver.find_element_by_id("userA") element.send_keys("admin1") time.sleep(2) element.send_keys(Keys.BACK_SPACE) # 2. 全选用户名 admin 暂停2s element.send_keys(Keys.CONTROL, "a") time.sleep(2) # 3. 复制用户名 admin 暂停2s element.send_keys(Keys.CONTROL, "c") time.sleep(2) # 4. 粘贴到电话输入框 driver.find_element_by_id("telA").send_keys(Keys.CONTROL, "v") time.sleep(5) driver.quit()
九、元素等待
由于一些原因, 我们想找的元素并没有立刻出来, 此时直接定位会报错, 场景如下:
-
网络速度慢
-
服务器计算慢
-
硬件配置差
思考: 是否定位每个元素时, 都需要元素等待?
隐式等待:
# 隐式等待为全局设置 (只需要设置1次,会作用于所有元素) # 参数: # timeout: 超时的时长, 单位: 秒 driver.implicitly_wait(timeout)
import time from selenium import webdriver driver = webdriver.Chrome() driver.get("file:///C:/Users/57769/Desktop/pagetest/%E6%B3%A8%E5%86%8CA.html") # 需求: 打开A页面, 使用隐式等待定位 "延时加载的输入框", 并输入 admin driver.implicitly_wait(10) driver.find_element_by_css_selector("input[placeholder='延时加载的输入框']").send_keys("admin") time.sleep(3) driver.quit() # 不使用元素等待时, 如果找不到元素会报 NoSuchElementException 异常 # 使用隐式等待时, 如果找不到元素会报 NoSuchElementException 异常
显式等待:
显式等待是针对特定的元素或特定条件等待的方式。通过指定等待条件和最长等待时间来等待元素或特定条件发生。一旦满足等待条件或者等待时间超时,则继续执行下一步操作。
要使用显式等待,首先需要导入 WebDriverWait
类和相应的等待条件类,然后使用 WebDriverWait
类来等待条件的出现。
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC driver = webdriver.Chrome() driver.get("http://example.com") # 设置显式等待,等待元素可见,最长等待时间为10秒 element = WebDriverWait(driver, 10).until( EC.visibility_of_element_located((By.ID, "myElement")) )
显式等待的语法是 WebDriverWait(driver, timeout).until(expected_condition)
,其中 timeout
是最长等待时间(秒),expected_condition
是一个预期条件对象,例如 visibility_of_element_located
表示等待元素可见。当预期条件发生或等待时间超时时,until
方法将返回等待的元素,或者抛出超时异常。
# 需求: 打开A页面, 使用显式等待定位 "延时加载的输入框", 并输入 admin wait = WebDriverWait(driver, 10, 1) element = wait.until(lambda x: x.find_element_by_css_selector("input[placeholder='延时加载的输入框']")) element.send_keys("admin")
# 显式等待, 为定位不同的元素的超时时间设置不同的值 1.导包 2.WebDriverWait(driver, timeout, poll_frequency=0.5) 1.driver: 浏览器驱动对象 2.timeout: 超时时长, 单位: 秒 3.poll_frequency: 检测的间隔时间, 默认为0.5s 3.调用 until(method) 1.method: 函数名称, 该函数用来实现元素定位 2.一般使用匿名来实现: lambda x: x.find_element_by_xxx("xxx") 如:element = WebDriverWait(driver,10,1).until(lambda x: x.find_element_by_xxx("xxx"))
隐式和显式区别:
1. 作用域: 隐式等待为全局有效, 显式等待为单个元素有效 2. 使用方法: 隐式等待直接通过驱动对象调用, 而显式等待方法封装在 WebDriverWait 类中 3. 达到最大超时时长后抛出异常不同: 隐式等待为 NoSuchElementException, 显式等待为 TimeoutException
十、下拉框&弹出框&滚动条操作
下拉框:
说明: Select类是Selenium为操作select标签封装的 实例化对象: select = Select(element) element: <select>标签对应的元素, 通过元素定位方式获取 例如: driver.find_element_by_id("selectA") 操作方法: 1. select_by_index(index) 根据option索引来定位, 从0开始 2. select_by_value(value) 根据option属性 value值来定位 3. select_by_visible_text(text) 根据option显示文本内容来定位
import time from selenium import webdriver from selenium.webdriver.support.select import Select driver = webdriver.Chrome() # 需求: 打开A页面,完成以下下拉框操作 # 1. 暂停2s, 选择广州 # 2. 暂停2s, 选择上海 # 3. 暂停2s, 选择北京 driver.get("file:///C:/Users/57769/Desktop/pagetest/%E6%B3%A8%E5%86%8CA.html") select = Select(driver.find_element_by_id("selectA")) # 1 time.sleep(2) select.select_by_index(2) # 2 time.sleep(2) select.select_by_value("sh") # 3 time.sleep(2) select.select_by_visible_text("北京") time.sleep(3) driver.quit()
弹出框:
说明: Selenium中对弹出框的处理, 有专用的方法, 且处理的方法都一样(alert/confirm/prompt) 1.获取弹出框对象 alert = driver.switch_to.alert 2.调用 alert.text 返回alert/confirm/prompt文字信息 alert.accept() 接受对话框选项(确认) alert.dismiss() 取消对话框选项(取消)
# 需求: 打开A页面,完成以下弹出框操作 # 1.点击 alert 按钮 # 2.暂停2s, 输入用户名 admin driver.get("file:///C:/Users/57769/Desktop/pagetest/%E6%B3%A8%E5%86%8CA.html") # 1 driver.find_element_by_id("alerta").click() time.sleep(2) alert = driver.switch_to.alert print(alert.text) time.sleep(2) alert.accept() # 2 time.sleep(2) driver.find_element_by_id("userA").send_keys("admin")
滚动条:
import time from selenium import webdriver driver = webdriver.Chrome() # 需求: 打开A页面 driver.get("file:///C:/Users/57769/Desktop/pagetest/%E6%B3%A8%E5%86%8CA.html") # js1 滚动到最底部 js1 = "window.scrollTo(0, 10000)" # js2 滚动到最顶部 js2 = "window.scrollTo(0, 0)" # 执行第一个脚本 time.sleep(2) driver.execute_script(js1) # 执行第二个脚本 time.sleep(2) driver.execute_script(js2) time.sleep(3) driver.quit()
十一、frame切换
frame : html页面中的一种框架, 主要作用是在当前页面指定区域显示另一个页面元素
形式一:
<frameset cols="25%,75%">
<frame src="a.html">
<frame src="b.html">
</frameset>
形式二:
<iframe name="iframe_a" src="demo.html" width="200" height="200"></iframe>
说明: 在Selenium中封装了如何切换frame框架的方法 步骤: 1.driver.switch_to.frame(frame_reference) 切换到指定frame frame_reference: 可以传frame框架的id,name,定位的frame元素 2.driver.switch_to.default_content() 恢复默认页面 必须回到默认页面才能进一步操作
import time from selenium import webdriver driver = webdriver.Chrome() # 需求: 打开"注册实例"页面 driver.get("file:///C:/Users/57769/Desktop/pagetest/%E6%B3%A8%E5%86%8C%E5%AE%9E%E4%BE%8B.html") # 1.填写主页面的用户名 admin time.sleep(2) driver.find_element_by_id("userA").send_keys("admin") # 2.填写注册页面A中的用户名 adminA time.sleep(2) # driver.switch_to.frame("idframe1") # 从主页面, 切换到了A页面, 通过 id # driver.switch_to.frame("myframe1") # 从主页面, 切换到了A页面, 通过 name driver.switch_to.frame(driver.find_element_by_id("idframe1")) # 从主页面, 切换到了A页面, 通过 定位到的元素 driver.find_element_by_id("userA").send_keys("adminA") # 3.回到主页面 time.sleep(1) driver.switch_to.default_content() # 4.填写注册页面B中的用户名 adminB time.sleep(1) driver.switch_to.frame("idframe2") # 从主页面, 切换到B页面 driver.find_element_by_id("userA").send_keys("adminB") time.sleep(3) driver.quit()
十二、多窗口切换
为什么要切换窗口? 在html页面中, 当点击按钮或超链接时, 有的会在新窗口打开页面
说明: 在Selenium中封装了获取当前窗口句柄,获取所有窗口句柄和切换到指定句柄窗口的方法 句柄: 英文handle, 窗口的唯一识别码 方法: 1.driver.current_window_handle 获取当前窗口句柄 2.driver.window_handles 获取所有窗口句柄 3.driver.switch_to.window(handle) 切换到指定句柄的窗口
对于需求的解决方案: 1. 打开A页面, 获取当前窗口句柄(拿到的是A页面的句柄) 2. 在A页面点击"访问 新浪 网站" 这个超链接, 获取所有窗口句柄 3. 根据句柄, 切换到新浪窗口, 对输入框输入 "新浪搜索" 4. 切换回原本窗口(A页面), 输入用户名 admin 注意: 新浪页面需要访问网络, 可能加载慢, 可能需要用到元素等待
import time from selenium import webdriver driver = webdriver.Chrome() # 隐式等待10秒, 以防新浪窗口加载慢, 定位不到输入框 driver.implicitly_wait(10) # 1. 打开A页面, 获取当前窗口句柄(拿到的是A页面的句柄) driver.get("file:///C:/Users/57769/Desktop/pagetest/%E6%B3%A8%E5%86%8CA.html") print("当前A页面窗口句柄:", driver.current_window_handle) # 2. 在A页面点击"访问 新浪 网站" 这个超链接, 获取所有窗口句柄 driver.find_element_by_id("fw").click() handles = driver.window_handles print("所有窗口句柄:", handles) # 3. 根据句柄, 切换到新浪窗口, 对输入框输入 "新浪搜索" driver.switch_to.window(handles[1]) time.sleep(1) driver.find_element_by_class_name("inp-txt").clear() time.sleep(1) driver.find_element_by_class_name("inp-txt").send_keys("新浪搜索") time.sleep(2) # 4. 切换回原本窗口(A页面), 输入用户名 admin driver.switch_to.window(handles[0]) driver.find_element_by_id("userA").send_keys("admin") time.sleep(3) driver.quit()
十三、窗口截图
说明: 在Selenium中提供了截图方法, 我们只需要调用即可
方法:
driver.get_screenshot_as_file(imgpath)
imgpath: 图片保存路径 + 图片名
import time from selenium import webdriver driver = webdriver.Chrome() # 需求: 打开 A 页面, 完成以下操作 # 1.输入用户名 admin # 2.截图保存 driver.get("file:///C:/Users/57769/Desktop/pagetest/%E6%B3%A8%E5%86%8CA.html") # 1 driver.find_element_by_id("userA").send_keys("admin") # 2 time.sleep(1) # 每次都是用固定文件名, 会股改上一次生成的图片文件 # driver.get_screenshot_as_file("./png/123.png") # 需要提前创建 png 目录 # 使用时间去格式化文件名, 可以使每次截图保存的文件名都不同, 不会覆盖之前保存的文件, 更有效 imgpath = "./png/test_{}.png".format(time.strftime("%Y%m%d%H%M%S")) driver.get_screenshot_as_file(imgpath) time.sleep(3) driver.quit()
十四、验证码处理
说明: Selenium中并没有对验证码处理的方法, 在这里我们介绍几种常用的处理方式 方法: 1.去掉验证码 (测试环境下采用) 2.设置万能验证码 (生产和测试环境下采用) 3.验证码识别技术 (通过 python-tesseract 来识别图片类型的验证码: 识别率很难达到100%) 4.记录 cookie (通过记录 cookie 进行跳过登录) ps: 1 和 2, 都是开发人员来完成, 我们不讲解 3 验证码识别技术成功率不高, 不太合适 4 记录cookie 比较实用, 推荐
1. cookie是由web服务器生成的, 并且保存在用户浏览器上的小文本文件, 它可以包含用户信息 2. cookie数据格式: 键值对 (python中的字典) 3. cookie产生: 客户端请求服务器, 如果服务器需要记录该用户状态, 就向客户端浏览器颁发一个cookie数据 4. cookie使用: 当浏览器再次请求该网站时, 浏览器把请求的数据和cookie数据一同提交给服务器, 服务器检查该cookie, 以此来辨认用户
cookie应用场景: 1. 实现会话跟踪, 记录用户登录状态 2. 实现记住密码和自动登录的功能 3. 用户未登录状态下, 记录购物车中的商品
说明: Selenium中对cookie操作提供相应的方法 方法: 1.driver.get_cookies() 获取本网站所有本地cookies 2.driver.get_cookie(name) 获取指定cookie name: 为cookie中键值对数据的 键名 3.driver.add_cookie(cookie_dict) 添加cookie cookie_dict: 一个字典对象, 必选的内容包括: "name" 和 "value"
需求: 使用cookie 实现跳过百度登录 1. 手动登录百度, 获取cookie 2.请求百度, 并且带上cookie 步骤分析: BDUSS是登录百度后的唯一身份凭证, 拿到BDUSS就等于拿到了账号的控制权,通行贴吧,知道,文库...主要产品 1.登录百度, 抓取BDUSS 2.添加 BDUSS 的键值对 3.调用刷新的方法
import time from selenium import webdriver driver = webdriver.Chrome() driver.maximize_window() # 需求: 使用cookie 实现跳过百度登录 # 1.手动登录百度, 获取cookie # 2.请求百度, 并且带上cookie # 没有cookie的时候 driver.get("http://www.baidu.com") # 添加cookie操作 driver.add_cookie({"name": "BDUSS", "value": "VZMUEl0WFJQYkxNSXk0c0VMUk5ZNGYteWVYNG01aVJtZXFCV056alk5M3V3SUZlSVFBQUFBJCQAAAAAAAAAAAEAAAC2KUFmTFhKX0pheQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO4zWl7uM1peQ"}) time.sleep(3) # 刷新, 再次请求百度首页, 验证是否带上身份信息 driver.refresh() time.sleep(3) driver.quit()
标签:Web,元素,webdriver,time,driver,element,测试,自动化,find From: https://www.cnblogs.com/meifirst/p/18211165