当前位置: 首页 > news >正文

手机网站免费制作贵州光利达建设工程有限公司局网站

手机网站免费制作,贵州光利达建设工程有限公司局网站,棒的网页设计,将自己做的网站用电脑发到网上文章目录 一、web UI自动化介绍1.1 执行UI自动化测试前提1.2 Selenium介绍以及知识点梳理 二、Selenium 学习2.1 基础2.1.1 环境安装与基础使用2.1.2 web浏览器控制2.1.3 常见控件的八大定位方式2.1.3.1 八大定位方式介绍2.1.3.2 NAME、ID定位2.1.3.3 css_selector定位2.1.3.4 … 文章目录 一、web UI自动化介绍1.1 执行UI自动化测试前提1.2 Selenium介绍以及知识点梳理 二、Selenium 学习2.1 基础2.1.1 环境安装与基础使用2.1.2 web浏览器控制2.1.3 常见控件的八大定位方式2.1.3.1 八大定位方式介绍2.1.3.2 NAME、ID定位2.1.3.3 css_selector定位2.1.3.4 通过XPATH定位 2.1.4 强制等待与隐式等待2.4.1 **强制直接等待**2.4.2 **隐式等待**2.4.3 **显式等待**2.4.4 总结 2.1.5 常见控件的交互方法2.1.6 练习1-测试人论坛搜索自动化 2.2 进阶2.2.1 css selector定位2.2.1.1 css 选择器概念2.2.1.2 CSS基础语法调试方法css基础语法关系定位css 顺序关系 2.2.2 XPATH定位2.2.2.1 xpath 基本概念2.2.2.2 XPTAH基础语法**调试方法**基础语法 2.2.2.3 xpath 高级用法 2.2.3 显示等待的高级应用原理解析官方分装类 expected_conditions自定义显示等待条件 2.2.4高级控件的交互方法介绍ActionChains基本用法键盘操作鼠标操作 2.25 网页多窗口和Frame的处理多窗口处理Frame的处理 文件上传以及弹窗处理文件上传弹窗处理 关键数据记录介绍示范 练习项目1-litemall商城管理后台前置后置操作登录功能新增商品删除商品新增商品测试用例 2.3 高级2.3.1 浏览器复用-托管2.3.2 cookie复用2.3.3 Page Object思想2.3.4 异常记录关键信息常规的记录方法使用装饰器记录 UI自动化的常见项目结构 一、web UI自动化介绍 1.1 执行UI自动化测试前提 业务流程不频繁改动UI 元素不频繁改动界面稳定需要频繁回归的场景多平台运行组合遍历型、大量重复的任务s 业界使用较多的web UI自动化工具是 Selenium 1.2 Selenium介绍以及知识点梳理 支持多语言行业内最火最主流 用于web浏览器测试的工具 支持的浏览器包括IEFirefoxSafariChromeEdge等 使用简单可使用JavaPython等多种语言编写用例脚本 主要由三个工具构成WebDriver、IDE、Grid 能力建设——初级 Selenium 的架构 #mermaid-svg-bVWW9301hR1DxTsS {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-bVWW9301hR1DxTsS .error-icon{fill:#552222;}#mermaid-svg-bVWW9301hR1DxTsS .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-bVWW9301hR1DxTsS .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-bVWW9301hR1DxTsS .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-bVWW9301hR1DxTsS .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-bVWW9301hR1DxTsS .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-bVWW9301hR1DxTsS .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-bVWW9301hR1DxTsS .marker{fill:#333333;stroke:#333333;}#mermaid-svg-bVWW9301hR1DxTsS .marker.cross{stroke:#333333;}#mermaid-svg-bVWW9301hR1DxTsS svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-bVWW9301hR1DxTsS .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-bVWW9301hR1DxTsS .cluster-label text{fill:#333;}#mermaid-svg-bVWW9301hR1DxTsS .cluster-label span{color:#333;}#mermaid-svg-bVWW9301hR1DxTsS .label text,#mermaid-svg-bVWW9301hR1DxTsS span{fill:#333;color:#333;}#mermaid-svg-bVWW9301hR1DxTsS .node rect,#mermaid-svg-bVWW9301hR1DxTsS .node circle,#mermaid-svg-bVWW9301hR1DxTsS .node ellipse,#mermaid-svg-bVWW9301hR1DxTsS .node polygon,#mermaid-svg-bVWW9301hR1DxTsS .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-bVWW9301hR1DxTsS .node .label{text-align:center;}#mermaid-svg-bVWW9301hR1DxTsS .node.clickable{cursor:pointer;}#mermaid-svg-bVWW9301hR1DxTsS .arrowheadPath{fill:#333333;}#mermaid-svg-bVWW9301hR1DxTsS .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-bVWW9301hR1DxTsS .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-bVWW9301hR1DxTsS .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-bVWW9301hR1DxTsS .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-bVWW9301hR1DxTsS .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-bVWW9301hR1DxTsS .cluster text{fill:#333;}#mermaid-svg-bVWW9301hR1DxTsS .cluster span{color:#333;}#mermaid-svg-bVWW9301hR1DxTsS div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-bVWW9301hR1DxTsS :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} brower webdriver selenium client多语言 chrome IE FireFox chromedriver IEdriver GeckoDriver selenium python java ruby 在客户端通过各种语言调用selenium库selenium 调用对应的浏览器驱动通过浏览器驱动去操作浏览器进行各种操作。 形式章节描述知识点Web 自动化测试价值与体系价值体系 技术选型 学习路线知识点环境安装与使用selenium、 chromedriver、 firefox geckodriver知识点自动化用例录制selenium IDE、录制、回放、基本使用知识点自动化测试用例结构分析录制代码解析代码结构优化知识点web 浏览器控制打开网页、刷新、回退、最大化、最小化知识点常见控件定位方法id name css xpath link 定位知识点强制等待与隐式等待介绍 selenium 经典的三种等待方式知识点常见控件交互方法点击输入清空获取元素文本、尺寸等属性信息实战测试人论坛搜索功能自动化测试用例设计、用例编写、断言 中级 形式章节描述知识点高级定位-csscss 使用场景、语法知识点高级定位-xpathxpath 使用场景、语法知识点显式等待高级使用显式等待原理与使用知识点高级控件交互方法右键点击、页面滑动、表单填写等自动化动作知识点网页 frame 与多窗口处理多窗口多 frame 下的窗口识别与切换知识点文件上传弹框处理文件上传的自动化与弹框处理机制知识点自动化关键数据记录行为日志、截图page source实战电子商务产品实战用例设计、日志封装、测试报告训练营知名产品web自动化测试实战用例设计、日志封装、测试报告 高级 形式章节描述知识点浏览器复用利用远程调试技术实现自动化登录知识点Cookie 复用利用 cookie 复用实现自动化登录知识点page object 设计模式page object 模式的发展历史介绍、六大设计原则知识点异常自动截图测试用例失败时自动截图知识点测试用例流程设计测试装置的应用套件级别的初始化与清理、用例级别的初始化与清理实战电子商务产品实战page object 设计模式应用、BasePage 封装、基于 page object 模式的测试用例编写训练营web自动化测试进阶实战page object 设计模式应用、BasePage 封装、基于 page object 模式的测试用例编写 拓展 selenium高级用法 形式章节描述知识点selenium 多浏览器处理chrome、firefox 等浏览器的自动化支持知识点执行 javascript 脚本使用 selenium 直接在当前页面中进行 js 交互知识点selenium option 常用操作selenium option 的介绍与使用知识点capability 配置参数解析capability 用法 firefox chrome 等浏览器的专属 capability 新一代前端测试框架 形式章节描述知识点cypress 测试框架介绍web 自动化测试框架 cypress 二、Selenium 学习 2.1 基础 2.1.1 环境安装与基础使用 准备好Python环境(百度python安装教程) 准备好selenium依赖 pip install selenium driver的下载与配置以chrome为例 下载chrome的webdriver 官方链接 https://www.selenium.dev/documentation/en/webdriver/driver_requirements/ 淘宝镜像下载更快 https://npm.taobao.org/mirrors/chromedriver/ 在下载时需要 选择与浏览器对应的版本如果找不到完全一样的可以选取个最相近的一般大版本相同也是可以正常使用的 配置环境变量 为了能够直接使用webdriver而不是使用时去写死webdriver的地址需要将webdriver所在的文件夹路径加到 环境变量(PATH)中 验证 打开一个cmd命令行输入chromedriver --version 可以看到版本信息则说明chromedriver环境变量配置成功 在代码中import对应的依赖并打开百度 基本使用 from time import sleepfrom selenium import webdriver # 初始化浏览器驱动这里选择Chrome浏览器需要配置好webdriver的环境变量 driver webdriver.Chrome() # 浏览器打卡百度 driver.get(http://www.baidu.com) sleep(10) # 关闭浏览器 driver.close()运行脚本能成功打开百度则说明配置成功 2.1.2 web浏览器控制 在初始化driver后可以使用以下方法对浏览器进行控制 初始化driver即diver webdriver.Chrome 然后使用driver调用以下方法 方法使用场景操作getweb自动化测试第一步打开浏览器refresh模拟浏览器刷新浏览器刷新back模拟退回步骤浏览器退回maximize_window模拟浏览器最大化最大化浏览器minimize_window模拟浏览器最小化最小化浏览器 from time import sleep from selenium import webdriver # 初始化浏览器驱动这里选择Chrome浏览器需要配置好webdriver的环境变量 driver webdriver.Chrome() # 浏览器打卡百度 driver.get(https://ceshiren.com/) sleep(3) # 刷新页面 driver.refresh() driver.get(http://www.baidu.com) # 浏览器返回操作 driver.back() sleep(1) # 最小化窗口 driver.minimize_window() sleep(1) driver.maximize_window() sleep(1) # 关闭浏览器 driver.close()2.1.3 常见控件的八大定位方式 2.1.3.1 八大定位方式介绍 控件的定位方式很多但常用的只有以下四种id、name、xpath、css selector 后续会详细介绍 方式描述使用方法id重点id 属性对应的值driver.find_element(By.ID, “ID属性”)name重点name 属性对应的值driver.find_element(By.NAME, “Name属性对应的值”)xpath重点xpath表达式driver.find_element(By.XPATH, “xpath表达式”)css selector重点css 表达式driver.find_element(By.CSS_SELECTOR, “css表达式”)link text查找其可见文本与搜索值匹配的锚元素driver.find_element(By.LINK_TEXT,“文本信息”)partial link text查找其可见文本包含搜索值的锚元素。如果多个元素匹配则只会选择第一个元素。class nameclass 属性对应的值driver.find_element(By.CLASS_NAME,‘el-submenu__title’)tag name标签名称很少用 使用格式 # 示例两种方式作用一模一样 # 官方建议使用下面的方式 driver.find_element_by_id(su) driver.find_element(By.ID, su) # 推荐你使用通过ID定位driver.find_element(By.ID, ID属性对应的值) import time from selenium import webdriver from selenium.webdriver.common.by import By driver webdriver.Chrome() driver.get(https://ceshiren.com/) # 强制等待3秒等待元素加载完毕 time.sleep(3) # 点击类别 ele driver.find_element(By.ID,ember24).click() time.sleep(30)2.1.3.2 NAME、ID定位 name定位格式driver.find_element(By.NAME, Name属性对应的值)id定位格式driver.find_element(By.ID, ID对应的值) 2.1.3.3 css_selector定位 格式 driver.find_element(By.CSS_SELECTOR, css表达式)复制绝对定位编写 css selector 表达式后面章节详细讲解 2.1.3.4 通过XPATH定位 格式 driver.find_element(By.XPATH, xpath表达式) chrome复制绝对定位 编写 xpath 表达式后面章节详细讲解 2.1.4 强制等待与隐式等待 ​ 在chrome打开网页的时候有时候由于网络加载、渲染等问题无法定位到元素需要等待元素加载渲染否则会出现异常的报错比如找不到元素等。 ​ 等待元素加载分为以下三种强制等待、隐式等待、以及显示等待 2.4.1 强制直接等待 原理直接在操作元素前添加sleep() 函数直接等待几秒让元素加载成功 缺点难以确定元素加载的具体等待时间时间短了无法定位到元素时间长了影响执行效率可以通过隐式等待解决 2.4.2 隐式等待 原理设置一个等待时间轮询查找默认0.5秒元素是否出现如果没出现就抛出异常 隐式等待相比强制等待更智能在脚本中我们一般看不到等待语句但是它会在每个页面加载的时候自动等待隐式等待只需要声明一次一般在打开浏览器后进行声明. 声明之后对整个drvier的生命周期都有效后面不用重复声明。 driver.implicitly_wait(3)缺点 元素可以找到使用点击等操作出现报错 原因 页面元素加载是异步加载过程通常html会先加载完成js、css其后导致进行交互操作时失败元素存在与否是由HTML决定元素的交互是由css或者js决定隐式等待只关注元素能不能找到不关注元素能否点击或者进行其他的交互 2.4.3 显式等待 原理在最长等待时间内轮询是否满足结束条件 格式: WebDriverWait(driver实例, 最长等待时间, 轮询时间).until(结束条件) def wait_until():driver webdriver.Chrome()driver.get(https://vip.ceshiren.com/#/ui_study)WebDriverWait(driver, 10).until(expected_conditions.element_to_be_clickable((By.CSS_SELECTOR, #success_btn)))driver.find_element(By.CSS_SELECTOR, #success_btn).click()2.4.4 总结 类型使用方式原理适用场景直接等待time.sleep(等待时间))强制线程等待调试代码临时性添加隐式等待driver.implicitly_wait(等待时间)在时间范围内轮询查找元素解决找不到元素问题无法解决交互问题显式等待WebDriverWait(driver实例, 最长等待时间, 轮询时间).until(结束条件)设定特定的等待条件轮询操作解决特定条件下的等待问题比如点击等交互性行为 2.1.5 常见控件的交互方法 点击 click() # 点击百度搜索框 driver.find_element(By.ID,kw).click()输入 send_keys(xx) # 输入霍格沃兹测试开发 driver.find_element(By.ID,kw).send_keys(霍格沃兹测试开发)清空 clear() # 清空搜索框中信息 driver.find_element(By.ID,kw).clear()获取元素属性信息 目的根据这些信息进行断言或者调试 获取元素信息的方法 获取元素文本获取元素的属性html的属性值 # 获取元素文本 driver.find_element(By.ID, id).text # 获取这个元素的name属性的值 driver.find_element(By.ID, id).get_attribute(name)2.1.6 练习1-测试人论坛搜索自动化 测试人搜索功能测试—进入测试人论坛首页(https://ceshiren.com) 点击搜索按钮输入搜索关键词输入回车进行搜索 预期结果判断 搜索成功搜索结果列表包含关键字 from time import sleepfrom selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions from selenium.webdriver.support.wait import WebDriverWaitclass TestCeshirenSearch:def setup_class(self):# 初始化driver并打开首页self.driver webdriver.Chrome()self.driver.get(https://ceshiren.com)# 设置 隐式等待,整个测试期间只需要设置一次self.driver.implicitly_wait(5)def teardown_class(self):sleep(3)# 关闭 浏览器self.driver.close()def test_search(self):# 点击搜索 按钮self.driver.find_element(By.ID, search-button).click()# 在搜索输入框输入pytestself.driver.find_element(By.ID, search-term).send_keys(pytest)# 显示等待5秒直到 搜索结果 按钮可点击WebDriverWait(self.driver, 5).until(expected_conditions.element_to_be_clickable(self.driver.find_element(By.CSS_SELECTOR, .results)))# 查看搜索结果 并根据 结果中是否包含搜索的元素进行 断言el_topic_list self.driver.find_element(By.CSS_SELECTOR, .topic-list-body)topic_title_text el_topic_list.textassert pytest in topic_title_text2.2 进阶 HTML中常用标签定位方式一般选取 css定位 或者xpath 定位需要对html中常用标签有一定的了解以下是一些基本的标签 标题h1、h2、h3、h4、h5、h6、title 段落p 链接a 图像img 样式style 列表无序列表ul、有序列表ol、列表项li 块div、span 脚本script 注释!--注释--2.2.1 css selector定位 2.2.1.1 css 选择器概念 css selector 定位 实际就是HTML的 Css选择器 的标签定位 css 定位可以支持web端的产品也可支持app端的webview场景 css 选择器有自己的语法规则和表达式 css 定位通常分为绝对定位和相对定位 # 绝对定位 $(#ember63 td.main-link.clearfix.topic-list-data span span a) # 相对定位 $(#ember63 [title新话题])从上可以看到相对定位更加简洁优雅此外相对定位还有以下有点不 可维护性更强语法更加简洁解决各种复杂的定位场景 2.2.1.2 CSS基础语法 使用css相对定位需要使用的对应的基础语法使用基础语法可以使用chrome自带的console 进行调试判断 调试方法 在浏览器(如:Chrome) 上按F12或者鼠标右键检查 进入console 输入 $(css表达式) 或者 $$(css表达式) 回车后查看是否定位到准确的结果 css基础语法 css 可以定位html 元素中的标签、id、类、以及其他属性进行定位,详细介绍如下 **PS注意**对于class 属性如果属性值有空格 类似这样的classnav-item_top top ember-view 其中的空格 并不是字符串而是作为分隔符表示class 有多个属性值定位时选取一个不对导致的重复的属性值即可(其他属性对应的属性值是唯一的) 类型表达式浏览器console中的写法示例标签标签名$(‘标签名’)$(‘li’)类.class属性值$(‘.类的值’)$(‘.nav-item_top’)ID#id属性值$(‘#id属性值’)$(‘#ember85’)属性[属性名‘属性值’] ( [ 属性名 ′ 属性 值 ′ ] ) 或者 b r ([属性名属性值])或者br ([属性名′属性值′])或者br(‘[属性名“属性值”]’)$(“[title‘过去一年、一个月、一周或一天中最活跃的话题’]”) 示例对应的html结构 关系定位 类型格式说明浏览器console中的写法父子元素元素$(‘#s_kw_wrapinput’)后代元素 元素节点子节点及子节点的所有子节点$(‘#form input’)并集(了解)元素,元素只要有一个元素存在就返回定位结果$(‘.bg,.s_ipt_wr,.new-pmd,.quickdelete-wrap’)邻近兄弟了解即可元素****元素元素在同一个父节点下且相邻$(‘.soutu-btninput’)兄弟了解即可元素1~元素2元素在同一个父节点下$(‘.soutubtni’) 示例: 以下为输入chrome console的语法 父子关系——定位节点1下的子节点2 $(#ember206#ember208)后代关系——定位节点1的后代节点4 $([idember206] [title有新帖子的话题]) PS: id属性也是属性的一种因此也可使用属性的语法临近兄弟——定位节点2的临近兄弟节点3 $(#ember208[idnavigation-bar])兄弟——定位节点4的兄弟节点6$(#ember213~#ember216)并集关系——定位节点4和节点6 $(#ember213,#ember216) 只要能知道到其中一个就返回结果 css 顺序关系 类型格式jiei浏览器console中的写法父子关系顺序父-子:nth-child**(n)**$(‘#forminput:nth-child(2)’)父子关系标签类型顺序父-子:nth-of-type**(n)**$(‘#forminput:nth-of-type(1)’) 示例 定位 navigation-bar的第9个孩子 $([idnavigation-bar]li:nth-child(9)) 当父节点下的子节点 类型不一样又想找某个类型下的第几个元素时则可使用 第二种 即$([idnavigation-bar]li:nth-child(9)) 表示 定位 navigation-bar节点下的 li标签中的第9个 2.2.2 XPATH定位 2.2.2.1 xpath 基本概念 ​ XPath (XML Path Language) 是一门在 XML 文档中查找信息的语言可用来在 XML 文档中对元素和属性进行遍历可以使用路径表达式来选取 XML 文档中的节点或者节点集也可以在web或者app自动化的测试中使用xpath 进行元素定位。 2.2.2.2 XPTAH基础语法 ​ 和css定位一样xpath 定位也分为绝对定位和相对定位绝对定位需要根节点开始一层一层的向下定位因此非常的臃肿且存在一旦前端修改了中间的某一个节点的依赖原来的表达式就会失效因此自动化中最后 使用简洁 优雅的相对定位。 XPATH相对定位的优点 可维护性更强语法更加简洁相比于css可以支持更多的方式 调试方法 浏览器-console $x(xpath表达式) 浏览器-elements ctrlf 输入xpath或者css 基础语法 表达式结果/从根节点的子元素选取绝对定位的开头整个页面 $x(/)//从符合条件的元素开始不考虑他们的位置相对定位常用开头*通配符nodename选取此节点的所有子节点…选取当前节点的父节点选取属性$x(‘//*[属性名“属性值”]’) 示例 输入Chrome console的命令 # 页面中的所有的子元素 $x(/*) # 整个页面中的所有元素 $x(//*) # 查找页面上面所有的div标签节点 $x(//div) # 查找id属性为site-logo的节点 $x(//*[idsite-logo]) # 查找节点的父节点 $x(//*[idsite-logo]/..)xpath通过索引直接获取对应元素 # 获取此节点下的所有的li元素 $x(//*[idember21]//li)# 获取此节点下【所有的节点的】第一个li元素 $x(//*[idember21]//li[1])2.2.2.3 xpath 高级用法 [last()]: 选取最后一个 # 选取最后一个input标签 //input[last()][属性名属性值 and 属性名属性值]: 与关系 # 选取属性name的值为passward并且属性pwd的值为123456的input标签 //input[namepassward and pwd123456][属性名属性值 or 属性名属性值]: 或关系 # 选取属性name的值为passward或属性pwd的值为123456的input标签 //input[namepassward or pwd123456][text()文本信息]: 根据文本信息定位 # 选取所有文本信息为霍格沃兹测试开发的元素 //*[text()霍格沃兹测试开发][contains(text(),文本信息)]: 根据文本信息包含定位 # 选取所有文本信息包霍格沃兹的元素 //*[contains(text(),霍格沃兹)]2.2.3 显示等待的高级应用 原理解析 ​ 由于页面元素加载是异步加载过程通常html会先加载完成js、css其后所以可能导致进行交互操作时失败因此可以利用selenium中的**WebDriverWait** 类来实现等待直到指定条件生效 或者 超出设定的时间。 显示等待的原理 在代码中定义等待一定条件发生后再进一步执行代码(解决元素已加载但js等交互未完全加载的问题)在最长等待时间内循环执行结束条件的函数WebDriverWait(driver 实例, 最长等待时间, 轮询时间).until(结束条件函数) WebDriverWait类的结构 #mermaid-svg-Jo8LTOsikz0YFOx2 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-Jo8LTOsikz0YFOx2 .error-icon{fill:#552222;}#mermaid-svg-Jo8LTOsikz0YFOx2 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Jo8LTOsikz0YFOx2 .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-Jo8LTOsikz0YFOx2 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Jo8LTOsikz0YFOx2 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Jo8LTOsikz0YFOx2 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Jo8LTOsikz0YFOx2 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Jo8LTOsikz0YFOx2 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Jo8LTOsikz0YFOx2 .marker.cross{stroke:#333333;}#mermaid-svg-Jo8LTOsikz0YFOx2 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Jo8LTOsikz0YFOx2 g.classGroup text{fill:#9370DB;fill:#131300;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-Jo8LTOsikz0YFOx2 g.classGroup text .title{font-weight:bolder;}#mermaid-svg-Jo8LTOsikz0YFOx2 .nodeLabel,#mermaid-svg-Jo8LTOsikz0YFOx2 .edgeLabel{color:#131300;}#mermaid-svg-Jo8LTOsikz0YFOx2 .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-Jo8LTOsikz0YFOx2 .label text{fill:#131300;}#mermaid-svg-Jo8LTOsikz0YFOx2 .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-Jo8LTOsikz0YFOx2 .classTitle{font-weight:bolder;}#mermaid-svg-Jo8LTOsikz0YFOx2 .node rect,#mermaid-svg-Jo8LTOsikz0YFOx2 .node circle,#mermaid-svg-Jo8LTOsikz0YFOx2 .node ellipse,#mermaid-svg-Jo8LTOsikz0YFOx2 .node polygon,#mermaid-svg-Jo8LTOsikz0YFOx2 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Jo8LTOsikz0YFOx2 .divider{stroke:#9370DB;stroke:1;}#mermaid-svg-Jo8LTOsikz0YFOx2 g.clickable{cursor:pointer;}#mermaid-svg-Jo8LTOsikz0YFOx2 g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-Jo8LTOsikz0YFOx2 g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-Jo8LTOsikz0YFOx2 .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-Jo8LTOsikz0YFOx2 .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-Jo8LTOsikz0YFOx2 .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-Jo8LTOsikz0YFOx2 .dashed-line{stroke-dasharray:3;}#mermaid-svg-Jo8LTOsikz0YFOx2 #compositionStart,#mermaid-svg-Jo8LTOsikz0YFOx2 .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Jo8LTOsikz0YFOx2 #compositionEnd,#mermaid-svg-Jo8LTOsikz0YFOx2 .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Jo8LTOsikz0YFOx2 #dependencyStart,#mermaid-svg-Jo8LTOsikz0YFOx2 .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Jo8LTOsikz0YFOx2 #dependencyStart,#mermaid-svg-Jo8LTOsikz0YFOx2 .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Jo8LTOsikz0YFOx2 #extensionStart,#mermaid-svg-Jo8LTOsikz0YFOx2 .extension{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Jo8LTOsikz0YFOx2 #extensionEnd,#mermaid-svg-Jo8LTOsikz0YFOx2 .extension{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Jo8LTOsikz0YFOx2 #aggregationStart,#mermaid-svg-Jo8LTOsikz0YFOx2 .aggregation{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Jo8LTOsikz0YFOx2 #aggregationEnd,#mermaid-svg-Jo8LTOsikz0YFOx2 .aggregation{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Jo8LTOsikz0YFOx2 .edgeTerminals{font-size:11px;}#mermaid-svg-Jo8LTOsikz0YFOx2 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} WebDriverWait POLL_FREQUENCY: float 0.5 轮询间隔 __init__(driver,timeout,poll_frequency,ignored_exceptions) until(self, method, message: str ) until_not(self, method, message: str ) 在WebDriverWait 类中一个属性POLL_FREQUENCY表示轮询的间隔还有3个函数分别是 构造函数init、直到条件成立函数until 和 直到条件不成立函数unitil_not。 在构造函数中 需要传入 webdriver的实例化对象driver、超时时间timeout、以及轮询间隔poll_frequency默认轮询间隔为0.5秒。 其中until 方法中需要传入一个 函数对象以及提示信息message(非必填) 其中until的源码如下(额外自己添加一点的注释 #mermaid-svg-wOcrEvo0mC1rtmwy {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-wOcrEvo0mC1rtmwy .error-icon{fill:#552222;}#mermaid-svg-wOcrEvo0mC1rtmwy .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-wOcrEvo0mC1rtmwy .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-wOcrEvo0mC1rtmwy .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-wOcrEvo0mC1rtmwy .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-wOcrEvo0mC1rtmwy .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-wOcrEvo0mC1rtmwy .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-wOcrEvo0mC1rtmwy .marker{fill:#333333;stroke:#333333;}#mermaid-svg-wOcrEvo0mC1rtmwy .marker.cross{stroke:#333333;}#mermaid-svg-wOcrEvo0mC1rtmwy svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-wOcrEvo0mC1rtmwy .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-wOcrEvo0mC1rtmwy .cluster-label text{fill:#333;}#mermaid-svg-wOcrEvo0mC1rtmwy .cluster-label span{color:#333;}#mermaid-svg-wOcrEvo0mC1rtmwy .label text,#mermaid-svg-wOcrEvo0mC1rtmwy span{fill:#333;color:#333;}#mermaid-svg-wOcrEvo0mC1rtmwy .node rect,#mermaid-svg-wOcrEvo0mC1rtmwy .node circle,#mermaid-svg-wOcrEvo0mC1rtmwy .node ellipse,#mermaid-svg-wOcrEvo0mC1rtmwy .node polygon,#mermaid-svg-wOcrEvo0mC1rtmwy .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-wOcrEvo0mC1rtmwy .node .label{text-align:center;}#mermaid-svg-wOcrEvo0mC1rtmwy .node.clickable{cursor:pointer;}#mermaid-svg-wOcrEvo0mC1rtmwy .arrowheadPath{fill:#333333;}#mermaid-svg-wOcrEvo0mC1rtmwy .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-wOcrEvo0mC1rtmwy .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-wOcrEvo0mC1rtmwy .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-wOcrEvo0mC1rtmwy .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-wOcrEvo0mC1rtmwy .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-wOcrEvo0mC1rtmwy .cluster text{fill:#333;}#mermaid-svg-wOcrEvo0mC1rtmwy .cluster span{color:#333;}#mermaid-svg-wOcrEvo0mC1rtmwy div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-wOcrEvo0mC1rtmwy :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} yes no No Yes 开始 结束 设置结束时间 设置死循环 调用method函数并赋值给value value真? 返回value值 捕获忽略的异常 等待一个轮询间隔 判断是否超时 跳出循环 抛出超时异常 def until(self, method, message: str ):screen Nonestacktrace None# 结束时间 当前的时间(单调时间的秒数) 构造函数初始化时传入的超时时间end_time time.monotonic() self._timeout# 设置死循环while True:try:# 调用 传入的函数名该函数的参数是 driver的实例化对象并将返回值赋值给valuevalue method(self._driver)# 当为True时 return 函数结束if value:return value# 捕获忽略传入的异常except self._ignored_exceptions as exc:screen getattr(exc, screen, None)stacktrace getattr(exc, stacktrace, None)# 等待一个轮询间隔time.sleep(self._poll)# 当超出 结束时间时 跳出循环if time.monotonic() end_time:break# 抛出超时异常raise TimeoutException(message, screen, stacktrace)官方分装类 expected_conditions 官网说明: https://www.selenium.dev/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.expected_conditions.html 官方为显示等待封装了许多的条件函数在expected_conditions类中有以下常用的条件方法 常见 expected_conditions 类型示例方法说明elementelement_to_be_clickable() 常用visibility_of_element_located()针对于元素比如判断元素是否可以点击或者元素是否可见urlurl_contains()针对于urltitletitle_is()针对于标题frameframe_to_be_available_and_switch_to_it(locator)针对于framealertalert_is_present()针对于弹窗 自定义显示等待条件 部分按钮处于可点击状态但是有时候点击一次元素未生效需要多次点击元素因此需要设计一个条件函数在点击后返回需要的一个新的元素当点击一次时无法找到元素会返回为None此时until方法会在等待时间内重复执行该函数。 from time import sleepfrom selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.wait import WebDriverWaitdriver webdriver.Chrome() driver.get(https://vip.ceshiren.com/#/ui_study/frame) driver.maximize_window()def multi_clickable(target_ele, next_ele):点击元素直到出现预期的新元素点击目标元素返回点击后出现的新元素没有则返回None:param target_ele: 需要点击的目标元素,如(By.ID, primary_btn),传入的是一个元组:param next_ele: 点击目标元素的后需要返回的新元素:return:def _predicate(driver):# 点击目标元素driver.find_element(*target_ele).click()# 返回期待的下一个元素不存在时返回Nonereturn driver.find_element(*next_ele)return _predicateWebDriverWait(driver, 10).until(multi_clickable((By.ID, primary_btn),(By.XPATH,//*[text()该弹框点击两次后才会弹出])) )2.2.4高级控件的交互方法 介绍 在进行selenium 操作时有些场景需要模拟键鼠操作才可以实现比如 复制粘贴、元素的拖拽等selenium中提供ActionChains来实现相关的操作 使用场景对应事件复制粘贴键盘事件拖动元素到某个位置鼠标事件鼠标悬停鼠标事件滚动到某个元素滚动事件使用触控笔点击触控笔事件了解即可 ActionChains基本用法 ​ 在进行网页交互通常还有右击、双击、鼠标悬停、拖拽、ctrlc复制以及粘贴大写输入等控制在selenium中提供了ActionChains类来实现各种键鼠操作。 ​ 当我们调用ActionChains的方法时不会立即执行而是会将所有的操作按顺序存放在一个队列里当调用perform()方法时队列中的事件才会依次执行。 ​ 使用的基本语法如下 ​ 实例化化 ActionChains类: ActionChains(driver) ,其中driver为webdriver # 实例化时传入webdriver调用perform()后操作才会执行 ActionChains(self.driver).操作.perform()键盘操作 按下/释放某个键位 按下shift 键 key_down(Keys.SHIFT, ele) 其中ele 为定位的元素必传 释放shift建 key_up(Keys.SHIFT,el)其中ele 为定位的元素必传 按键输入字符 输入 selenium send_keys(selenium) 输入回车 直接输入回车: 元素.send_keys(Keys.ENTER) 使用ActionChains: key_down(Keys.ENTER) 复制、粘贴、剪切—组合键位 上诉三个设计多个案件其中需要用到的ctr 可以通过 key_down()方法进行控制c、v、x 可以通过send_keys()输入需要的按键需要注意的时需要考虑系统的兼容 多系统兼容 mac 的复制按钮为 command cwindows 的复制按钮为 ctrl c 示例在输入输入字符后全选剪切再进行粘贴 # 复制粘贴 win 和 mac 有所不同因此区分下 cmd_ctrl Keys.COMMAND if sys.platform darwin else Keys.CONTROL # 1.在输入框 先输入 chrome 2.ctra 全选 3.ctrx 剪切 4. ctrv 粘贴3次5.释放ctrl键 ActionChains(driver).send_keys(chrome).\key_down(cmd_ctrl,el_search_input).\send_keys(axvvv).\key_up(cmd_ctrl,el_search_input).perform()源码https://gitee.com/sailor233/seleniumDemo/blob/dev/try/keyboard2-copy-.py 鼠标操作 官网https://www.selenium.dev/documentation/webdriver/actions_api/mouse/ 双击double_click(元素对象)拖动元素drag_and_drop(起始元素对象, 结束元素对象)指定位置悬浮move_to_element(元素对象)鼠标右键context_click(元素对象)鼠标滚轮滚动操作(selenium 版本需要在 4.2 之后) 官网https://www.selenium.dev/documentation/webdriver/actions_api/wheel/滚动到元素scroll_to_element(WebElement对象)根据坐标滚动scroll_by_amount(横坐标, 纵坐标) #!/usr/bin/env python # -*- coding: utf-8 -*- # Time : 2023/7/4 23:00 # Author : sailor233 # File : ActionChains_MouseAction.py # Software: PyCharm # Des : ActionChains的鼠标操作 import timefrom selenium import webdriver from selenium.webdriver import ActionChains from selenium.webdriver.common.by import Bydriver webdriver.Chrome() driver.implicitly_wait(5) driver.get(https://vip.ceshiren.com/#/ui_study/mouseover)# 双击元素 ele_double driver.find_element(By.ID,primary_btn) ActionChains(driver).double_click(ele_double).perform() time.sleep(1) # 点击确定 driver.find_element(By.CSS_SELECTOR,.el-message-box__btnsbutton).click() time.sleep(2)# 鼠标移入悬浮 moveToEle driver.find_element(By.CSS_SELECTOR,[idmouseover]button) ActionChains(driver).move_to_element(moveToEle).perform() time.sleep(1)# 鼠标右键 driver.get(https://vip.ceshiren.com/#/ui_study/clicks) right_ele driver.find_element(By.CSS_SELECTOR,[idrightClick]button) ActionChains(driver).context_click(right_ele).perform() time.sleep(2)# 元素拖拽 driver.get(https://vip.ceshiren.com/#/ui_study/action_chains) start_ele driver.find_element(By.ID,item1) end_ele driver.find_element(By.ID,item3) ActionChains(driver).drag_and_drop(start_ele,end_ele).perform() time.sleep(3)2.25 网页多窗口和Frame的处理 多窗口处理 在网页点击链接时会打开新的窗口如果我们想要在新的窗口进行操作就需要先切换窗口。每个窗口都有一个句柄作为唯一标识因此我们可以通过切换句柄来实现多个页面之前的灵活操作。 多窗口的处理流程 先获取当前窗口的窗口句柄(dirver.current_window_handle)返回句柄标识一个字符串 如B351ACAA077B689431FA53199D88D0C0 获取所有的窗口句柄driver.window_handles返回一个列表包含所有的句柄标识 如 [B351ACAA077B689431FA53199D88D0C0, CB85E316C47BC4C8B3A2FE51F0C0D736] 判断当前窗口是否为想操作的窗口如果是则对窗口进行操作否则切换窗口 driver.switch_to.window(all_windows[0]) 案例 打开百度页面点击登录弹框点击 立即注册 输入用户名和手机号返回刚才的登录页面输入用户名、密码、点击登录 #!/usr/bin/env python # -*- coding: utf-8 -*- # Time : 2023/7/6 22:08 # Author : sailor233 # File : switch_window.py # Software: PyCharm # Des : selenium 多窗口切换操作 from time import sleepfrom selenium import webdriver from selenium.webdriver.common.by import Bydriver webdriver.Chrome() driver.implicitly_wait(5) driver.get(https://wwww.baidu.com)driver.find_element(By.LINK_TEXT,登录).click() # 查看当前句柄标识 print(driver.current_window_handle) driver.find_element(By.LINK_TEXT,立即注册).click() # 获取所有窗口的句柄标识 all_windows driver.window_handles print(all_windows:%s %all_windows) # 切换到新的窗口 driver.switch_to.window(all_windows[-1]) # 输入用户名、手机号 driver.find_element(By.ID,TANGRAM__PSP_4__userName).send_keys(zhangsan) driver.find_element(By.ID,TANGRAM__PSP_4__phone).send_keys(13594531258)# 切换会之前的窗口 driver.switch_to.window(all_windows[0]) # 输入 用户名 driver.find_element(By.ID,TANGRAM__PSP_11__userName).send_keys(lisi) # 输入密码 driver.find_element(By.ID,TANGRAM__PSP_11__password).send_keys(adasda) # 点击登录 driver.find_element(By.ID,TANGRAM__PSP_11__submit).click() sleep(5)Frame的处理 介绍 ​ 在web页面中html可以使用frame框架在一个主页面中利用frame创建不同的框架从而实现在一个web页面呈现多个页面每个frame框架的内容可以有自己的布局方式。因此有时定位不到元素可能就是因为元素那么可能元素在ifrme中可以查看元素是否被包含与frame标签中。 ​ w3c frame框架demohttps://www.w3school.com.cn/tiy/t.asp?feg_html_frame_cols 其中Frame分为3类 frame标签包含 frameset、frame、iframe三种其中frameset与其他标签一样可以使用id、name等selenium中任意支持的方式定位frame和iframe在selenium中有专门的定位方法 多Frame切换 根据frame的id或者index 切换 driver.switch_to.frame()切换到默认frame driver.swutch_to.default_conten()切换到父级frame(嵌套frame的情况): driver.swicth_to.parent_frame() 举例拖动元素其中两个元素在iframe中 ​ 演示环境https://www.runoob.com/try/try.php?filenamejqueryui-api-droppable #!/usr/bin/env python # -*- coding: utf-8 -*- # Time : 2023/7/10 23:28 # Author : sailor233 # File : frame.py # Software: PyCharm # Des : 演示地址https://www.runoob.com/try/try.php?filenamejqueryui-api-droppable from time import sleepfrom selenium import webdriver from selenium.webdriver import ActionChains from selenium.webdriver.common.by import Bydriver webdriver.Chrome() driver.implicitly_wait(5) driver.get(https://www.runoob.com/try/try.php?filenamejqueryui-api-droppable) # 切换到 iframe框架内 driver.switch_to.frame(iframeResult) ele_drag driver.find_element(By.XPATH,//*[text()请拖拽我]) ele_drop driver.find_element(By.XPATH,//*[text()请放置到这里]) ActionChains(driver).drag_and_drop(ele_drag,ele_drop).perform() # 切换会主框架 driver.switch_to.default_content() sleep(5)文件上传以及弹窗处理 文件上传 如果页面使用web页面使用 input标签实现文件上传可以直接使用send_keys(文件绝对地址)进行上传文件 步骤如下 找到上传按钮 el driver.find_element(By.CSS_SELECTOR,.upload-pic)使用上传按钮上传图片el.send_keys(jpg_path) ps 也可以直接合并为一步 举例使用百度首页点击图片上传功能上传图片 #!/usr/bin/env python # -*- coding: utf-8 -*- # Time : 2023/7/11 22:08 # Author : sailor233 # File : file_upload.py # Software: PyCharm # Des : 文件上传处理 import os import timefrom selenium import webdriver from selenium.webdriver.common.by import Bydriver webdriver.Chrome() driver.implicitly_wait(5) driver.get(https://www.baidu.com) # 点击 相机按钮 driver.find_element(By.CSS_SELECTOR,.soutu-btn).click() # 点击 选择文件 按钮 el driver.find_element(By.CSS_SELECTOR,.upload-pic)# 获取文件的绝对路径 jpg_path os.path.abspath(test.jpg) # 上传文件 el.send_keys(jpg_path)time.sleep(10)弹窗处理 在页面操作时有时候会出现由js生成的弹窗如alert、confirm以及prompt;在selenium中可以使用 switch_to.alert 进行定位。 常用方法如下 切换到弹框switch_to.alert获取弹窗中的文本信息text接受现有警告框accept()解散警告框dismiss()发送文本到警告框: send_keys() #!/usr/bin/env python # -*- coding: utf-8 -*- # Time : 2023/7/11 22:55 # Author : sailor233 # File : alert.py # Software: PyCharm # Des : from time import sleepfrom selenium import webdriver from selenium.webdriver import ActionChains from selenium.webdriver.common.by import Bydriver webdriver.Chrome() driver.implicitly_wait(5) driver.get(https://www.runoob.com/try/try.php?filenamejqueryui-api-droppable) # 切换到 iframe框架内 driver.switch_to.frame(iframeResult) ele_drag driver.find_element(By.XPATH,//*[text()请拖拽我]) ele_drop driver.find_element(By.XPATH,//*[text()请放置到这里]) ActionChains(driver).drag_and_drop(ele_drag,ele_drop).perform()# 切换到弹窗并点击确认 driver.switch_to.alert.accept() sleep(5)关键数据记录 介绍 ​ 为了后续排查错误需要将自动化执行过程中的关键数据记录下来关键数据执行日志、执行行为的截图、页面源码以下分别对三种数据的功能进行介绍 代码的执行日志 记录代码的执行记录方便复现场景可以作为bug依据用法在关键位置使用 logging库打印日志 代码执行的截图 断言失败或成功截图异常截图达到丰富报告的作用可以作为bug依据用法 driver.save_screenshot(./images/search1.png) page source页面源代码self.driver.page_source 协助排查报错时元素当时是否存在页面上 用法 # 在报错行前面添加保存page_source的操作 with open(record.html, w, encodingu8) as f:f.write(self.driver.page_source)示范 #!/usr/bin/env python # -*- coding: utf-8 -*- # Time : 2023/7/12 22:21 # Author : sailor233 # File : reord.py # Software: PyCharm # Des : # 日志与脚本结合 from selenium import webdriver from selenium.webdriver.common.by import Byfrom logUtil import loggerclass TestDataRecord:def setup_class(self):self.driver webdriver.Chrome()self.driver.implicitly_wait(3)def teardown_class(self):self.driver.quit()def test_log_data_record(self):# 实例化self.driversearch_content 霍格沃兹测试开发学社# 打开百度首页self.driver.get(https://www.sogou.com/)logger.debug(打开搜狗首页)# 输入霍格沃兹测试学院self.driver.find_element(By.CSS_SELECTOR, #query). \send_keys(search_content)logger.debug(f搜索的内容为{search_content})# 点击搜索self.driver.find_element(By.CSS_SELECTOR, #stb).click()# 搜索结果search_res self.driver.find_element(By.CSS_SELECTOR, em)# 保存搜索结构截图self.driver.save_screenshot(searchResult.jpg)# 保存页面源码with open(record.html, w, encodingu8) as f:f.write(self.driver.page_source)logger.info(f搜索结果为{search_res.text})assert search_res.text search_content日志模块 #!/usr/bin/env python # -*- coding: utf-8 -*- # Time : 2023/7/12 22:20 # Author : sailor233 # File : logUtil.py # Software: PyCharm # Des : # 日志配置 import logging # 创建logger实例 logger logging.getLogger(simple_example) # 设置日志级别 logger.setLevel(logging.DEBUG) # 流处理器 ch logging.StreamHandler() ch.setLevel(logging.DEBUG) # 日志打印格式 formatter logging.Formatter\ (%(asctime)s - %(name)s - %(levelname)s - %(message)s) # 添加格式配置 ch.setFormatter(formatter) # 添加日志配置 logger.addHandler(ch)练习项目1-litemall商城管理后台 在litemall管理商城后台 对商品类目进行添加 和删除 产品信息 地址http://litemall.hogwarts.ceshiren.com/#/dashboard使用账户用户名 manage 密码 manage123 实现的用例场景 用例标题前提条件执行步骤预期结果添加商品1. 登录并进入用户管理后台 2. 登录账号有商品管理的权限1. 点击增加 2. 输入商品名称和商品编号 3. 点击 上架1. 跳转商品列表 2. 新增在第一行行新增成功删除商品1. 进入用户管理后台 2. 商品列表里面有已存在的商品新增1. 点击删除按钮1. 是否有删除成功提示 2. 被删除商品不在商品类目列表展示 脚本编写思路 编写前置后置操作如drvier的初始化、登录平台等实现基本功能代码优化将强制等待换为隐式等待完善细节日志、报告、截图 前置后置操作 前置操作setup_class中实现浏览器的打开、隐式等待 后置操作teardown_class 中实现浏览器的关闭 class TestLiteMall:def setup_class(self):self.driver webdriver.Chrome() # 初始化driver使用chrome浏览器self.driver.maximize_window() # 最大化浏览器窗口self.driver.implicitly_wait(5) # 全局设置隐式等待5sdef teardown_class(self):self.driver.quit() # 退出浏览器实现基本功能 基本功能分为登录、新增商品、删除商品 登录功能 def login(self):实现登录功能:return:# 由于用户名 和 密码有原本文本需要先清除self.driver.find_element(By.NAME, username).clear()self.driver.find_element(By.NAME, username).send_keys(manage)self.driver.find_element(By.NAME, password).clear()self.driver.find_element(By.NAME, password).send_keys(manage123)# 点击登录按钮self.driver.find_element(By.CSS_SELECTOR, button).click()新增商品 def add_merchandise(self, merchandise_id, merchandise_name):添加商品:param merchandise_id:商品ID:param merchandise_name:商品名称:return: 无logger.info(点击商品管理)self.driver.find_element(By.XPATH, //*[text()商品管理]).click()logger.info(点金商品列表)self.driver.find_element(By.XPATH, //*[text()商品列表]).click()logger.info(点击点击按钮)self.driver.find_element(By.CSS_SELECTOR, .filter-containerbutton:nth-of-type(2)).click()logger.info(输入商品编号)self.driver.find_element(By.XPATH, //*[text()商品编号]/../div/div/input).send_keys(merchandise_id)logger.info(输入商品名称)self.driver.find_element(By.XPATH, //*[text()商品名称]/../div/div/input).send_keys(merchandise_name)logger.info(点击上架)self.driver.find_element(By.CSS_SELECTOR, .op-containerbutton:nth-child(2)).click()删除商品 def delet_merchandise(self, merchandise_id1439956):通过商品id删除商品:param merchandise_id:商品对应的id:return:logger.info(点击商品管理)self.driver.find_element(By.XPATH, //*[text()商品管理]).click()logger.info(点金商品列表)self.driver.find_element(By.XPATH, //*[text()商品列表]).click()logger.info(f通过商品id:{merchandise_id},定位到对应删除按钮后 点击删除)self.driver.find_element(By.XPATH, f//*[text(){merchandise_id}]/../../td[last()]/div/button[2]).click()新增商品测试用例 pytest.mark.parametrize(merchandise_id,merchandise_name, test_add_data) def test_add_merchandise(self, merchandise_id, merchandise_name):logger.info(f测试添加商品:{merchandise_id},{merchandise_name})self.add_merchandise(merchandise_id, merchandise_name)logger.info(断言出现提示信息:创建成功)WebDriverWait(self.driver, 3).until(expected_conditions.visibility_of_element_located((By.XPATH, //p[text()创建成功])))assert self.driver.find_element(By.XPATH, //p[text()创建成功]).text 创建成功2.3 高级 2.3.1 浏览器复用-托管 介绍 浏览器复用指的是 selenium代码执行调用的浏览器与我们当前使用的浏览器是一个而不是从新打开一个由selenium控制打开的浏览器这样实现便于自动测试过程中的人为介入从而提高测试效率。 如果seleniu控制打开时一个新的chrome不会携带任何cookie信息等不利用人工介入如扫码登陆、调式等具体场景举例 当运行 selenium 自动化时要求已经登录才能才做。这个时候我们可以提前登录运行脚本的时候复用已经打开的浏览器。当调试了某个步骤很多的测试用例前面N-1步已经成功只需调试第N步。如果从头开始运行脚本耗时过多这时我们可以直接复用浏览器手动操作第N不进行调试。 配置步骤 首先退出当前所有的谷歌浏览器其中windows还需打开任务管理器 查看chrome进程是否关闭 配置环境变量将chrome浏览器exe文件所在位置放到环境变量path中 验证是否配置成功 重新打开cmd命令输入以下命令打开浏览器 chrome --remote-debugging-port9222再打开的浏览器输入 localhost:9222 会打开一个空白页面或者一个简单页面 代码中使用 #!/usr/bin/env python # -*- coding: utf-8 -*- # Time : 2023/7/25 22:25 # Author : sailor233 # File : chrome_remote.py # Software: PyCharm # Des : from selenium import webdriver from selenium.webdriver.chrome.options import Optionsopt Options() # 地址要和cmd启动的一致chrome一致 opt.debugger_address localhost:9222 # 实例化driver传入 启动的chrome地址 driver webdriver.Chrome(optionsopt) # 使用已打开的chrome 打开百度而不是重新启动一个chrome浏览器 driver.get(http://www.baidu.com)2.3.2 cookie复用 cookie是什么 Cookie是保存在计算机上的一种文件。当我们使用计算机浏览网页时服务器会生成一个证书并将其返回给我们的计算机。这个证书是cookie。一般来说cookie是服务器写给客户端的文件也可以称为浏览器缓存复用已有的cookie可以直接登录不需要重新进行登录认证对于部分只能扫码登录的应用可以先登录后保存cookie后续直接使用cookie进行访问。 为什么需要复用cookie 复用浏览器仍然在每次用例开始都需要人为介入若用例需要经常执行复用浏览器则不是一个好的选择大部分cookie的时效性都很长扫一次可以使用多次 复用cookie的思路 打开浏览器扫码登录确保登录之后重点获取cookies检查本地文件是否已经获取成功再次打开浏览器通过cookie直接进入主页 代码实现 获取cookiedriver.get_cookies()添加cookie: driver.add_cookie(cookie) demo 企业微信登录cookie复用 #!/usr/bin/env python # -*- coding: utf-8 -*- # Time : 2023/7/26 21:58 # Author : sailor233 # File : test_cookie.py # Software: PyCharm # Des : from time import sleepimport yaml from selenium import webdriver def test_getcookie():driver webdriver.Chrome()driver.get(https://work.weixin.qq.com/wework_admin/loginpage_wx?frommyhome)# 获取cookie# get_cookie()add_cookies(driver)driver.refresh()sleep(5)def get_cookie(driver):# 获取cookiescookies driver.get_cookies()# 将获取到的cookie保存到文件中with open(cookie.yaml, w) as f:yaml.safe_dump(cookies, f)def add_cookies(driver):cookies yaml.safe_load(open(cookie.yaml))for cookie in cookies:driver.add_cookie(cookie)常见问题 获取cookie的时候即执行代码获取cookie时一定要确保已经登录植入cookie之后需要进入登录页面刷新验证是否自动登录成功。 2.3.3 Page Object思想 传统的UI自动化是线性脚本元素操作、断言等步骤混合在一起当UI存在变换时改动非常麻烦工作量很大也无法清晰的表达出业务用例的场景。 PO思想简介 把一个具体的页面转换成编程语言当中的一个类页面特性转化成对象属性页面操作转换成对象方法。 PO建模原则 字段意义 不要暴露页面内的所有元素给外部不需要建模UI内的所有元素元素很多无法重复建模选择重点元素 方法意义 用公共方法代表UI所提供的的功能方法应该返回其他PageObject的或者返回用于断言的数据同样的行为不同结果可以建模不同的方法不要在方法内加断言 以测试登录雪球测试为例 之前的线性脚本 class TestSearch:def test_search(self):# 初始化浏览器self.driver webdriver.Chrome()self.driver.get(https://xueqiu.com/)self.driver.implicitly_wait(3)# 输入搜索关键词self.driver.find_element(By.NAME, q).send_keys(阿里巴巴-SW)# 点击搜索按钮self.driver.find_element(By.CSS_SELECTOR, i.search).click()# 获取搜索结果name self.driver.find_element(By.XPATH, //table//strong).text# 断言assert name 阿里巴巴-SW使用PO思想设计测试脚本 先封装搜索页面 #!/usr/bin/env python # -*- coding: utf-8 -*- # File : search_page.py from selenium import webdriver from selenium.webdriver.common.by import By class SearchPage:__INPUT_SEARCH (By.NAME, q)__BUTTON_SEARCH (By.CSS_SELECTOR, i.search)__SPAN_STOCK (By.XPATH, //table//strong)def __init__(self):self.driver webdriver.Chrome()self.driver.implicitly_wait(3)self.driver.get(https://xueqiu.com/)def search_stock(self, stock_name: str):self.driver.find_element(*self.__INPUT_SEARCH).send_keys(stock_name)self.driver.find_element(*self.__BUTTON_SEARCH).click()name self.driver.find_element(By.XPATH, //table//strong).textreturn name测试用例 from search_page import SearchPage class TestSearch:def test_search(self):text SearchPage().search_stock(阿里巴巴-SW)# 断言assert 阿里巴巴-SW text2.3.4 异常记录关键信息 常规的记录方法 一般记录方式使用tryexcept 进行记录 import timeimport allure from selenium import webdriver from selenium.webdriver.common.by import By# 问题1 异常处理会影响用例本身的结果 # 解决方案 需要在异常处理后使用raise 再把异常抛出去# 问题2异常处理的逻辑与业务无关添加后显得非常冗余需要进行解耦 # 解决方案 使用装饰器进行异常逻辑的处理class TestBaidu:def test(self):driver webdriver.Chrome()driver.get(http://www.baidu.com)try:# 查找一个不存在的iddriver.find_element(By.ID, su1)except Exception:timestamp int(time.time())image_path f./images/image_{timestamp}.PNG # 需要先创建imagse目录# 保存截图driver.save_screenshot(image_path)# 保存源码page_path f./page_source/page_{timestamp}.html # 需要先创建page_source目录with open(page_path, w, encodingutf-8) as f:f.write(driver.page_source)# 将截图放入allure测试报告allure.attach.file(image_path, namepicture, attachment_typeallure.attachment_type.PNG)# 将源码放入allure测试报告allure.attach.file(page_path, namepagesoce, attachment_typeallure.attachment_type.HTML)raise Exception使用allure命令 可以生成测试报告 并看到执行后保存的数据 pytest --alluredir./report allure serve ./report存在的问题 由于添加了异常处理影响了用例本身的执行结果本该是执行失败的结果测试报告中显示 Passed 解决方式 在exception后捕获了异常并处理的最后增加语句抛出异常raise Exeception 执行结果pytest --alluredir./report 、 allure serve ./report 异常处理代码和业务无关不能耦合否则用例 解决方法使用装饰器就可以不体现在源码中 使用装饰器记录 装饰器函数 # 问题3 通driver进行截图时、获取源码时报错没有driver # 解决方案 通过debug可以看到args[0]中存在TestBaidu的实例对象它包含了实例属性self.driver # 因此可以通过# args[0].driver获取drievr# 问题4当某测试函数执行后没有返回值 # 解决方法 执行 装饰函数时需要return def ui_exception_record(func):def wrapper(*args, **kwargs):try:# 成功后需要返回,否则无法看到返回值return func(*args, **kwargs)except Exception:# 获取被装饰方式的实例对象self# 前提条件1.被装饰方法是一个实例方法 2.获取的变量也是实例变量即是self.driver# 根据调试 可以看到args[0]是类TestBaidu的实例对象存在实例属性 driverdriver args[0].driverprint(出现异常)timestamp int(time.time())image_path f./images/image_{timestamp}.PNG # 需要先创建imagse目录# 保存截图driver.save_screenshot(image_path)# 保存源码page_path f./page_source/page_{timestamp}.html # 需要先创建page_source目录with open(page_path, w, encodingutf-8) as f:f.write(driver.page_source)# 将截图放入allure测试报告allure.attach.file(image_path, namepicture, attachment_typeallure.attachment_type.PNG)# 将源码放入allure测试报告allure.attach.file(page_path, namepagesoce, attachment_typeallure.attachment_type.HTML)raise Exceptionreturn wrapper装饰执行测试函数 class TestBaidu:ui_exception_recorddef test(self):self.driver webdriver.Chrome()self.driver.get(http://www.baidu.com)self.driver.find_element(By.ID, su1)通过装饰器的使用在测试函数中出现异常的处理不体现在业务逻辑中程序变得非常优雅 UI自动化的常见项目结构 - page: 页面对象 - testcases: 测试用例 - utils: 公共工具 - log: 日志信息
http://www.dnsts.com.cn/news/168549.html

相关文章:

  • 站长工具seo综合查询隐私查询wordpress wp roket
  • 景安网站制作一个网址需要多少钱
  • 做网站页面提供的图结构一起做网站广州
  • 做网站做那一网站好普通建站
  • 五华网站建设wordpress网站扫描工具
  • 做网站公dw网页制作教程合集
  • 做外贸生意用哪个网站网站建设需要的一些技术
  • 苏州前几天网站建设网站开发文档doc
  • 小白怎样建设公司网站如何成为百度广告代理商
  • 大连建设学校网站院长山东建设公司网站
  • 品牌网站建设特色大蝌蚪行政部建设公司网站
  • 北京网站设计公司哪儿济南兴田德润简介潍坊网站排名
  • 网站标题替换企业免费发布信息平台
  • wordpress 提示插件安装插件seo怎么做新手入门
  • 合肥网站优化制作游戏需要学什么
  • 做类似电驴网站太原市免费网站建设
  • 网站域名的设置厚街网站建设
  • 江西建设信息港网站国外点击链接推广平台
  • 石家庄免费建站建站宝盒小程序
  • 陕西长城建设工程有限公司网站影楼网站建设
  • 2w网站2w网站建设建设聊城网站建设潍坊
  • 个网站做淘宝客推广可以吗网站建设实施步骤
  • 服饰工厂网站建设wordpress 生成app
  • 如何修改网站关键词外销网站建立
  • 外文网站搭建公司在线教育网站流量是怎样做的
  • 手举牌战队图片在线制作seo比较好的优化
  • 泉州公司网站模板建站湘潭网站建设公司
  • 有做酒席酒水网站吗游戏加盟公司
  • 青岛的网站建设益阳房产网站建设
  • 怎么做hello官方网站中小学网站建设方案