Selenium基础

1. selenium简介

用于实现自动化测试的 python 包,使用前需要安装对应浏览器驱动

from time import sleep
from selenium import webdriver
option = webdriver.ChromeOptions()
# 指定chrome存储路径的二进制形式
option.binary_location='D:\Chrome\Google\Chrome\Application\chrome.exe'
# 获取谷歌浏览器驱动
driver = webdriver.Chrome(options=option)
# 浏览器访问指定网站
driver.get('http://www.baidu.com')
# 3秒后浏览器关闭
sleep(3)

2. 控制组件的各种方式

# 在输入方法之前一定要清空操作
# 输入值为value的方法【文件上传按钮也使用send_keys(path)而不是click】
# ele为定位到的组件
ele.send_keys(value) 
# 点击方法
ele.click() 
# 清空
ele.clear() 

driver.find_element(s)

# 定位到id值为user的组件,并将'admin'填入
# by另外还能填name,class_name,xpath,css_selector等,返回WebElement单个元素
driver.find_element(by='id',value='user').send_keys('admin')
from selenium.webdriver.common.by import By
# find_elements中有s时,by参数需要传入By.xx属性,结果返回是list,装载多个WebElement元素
# 定位到tag为input的组件,并将'admin'填入第一个input组件中
driver.find_elements(by=By.TAG_NAME,value='input')[0].send_keys('admin')

超链接LINK_TEXT和PARTIAL_LINK_TEXT

from time import sleep
from selenium import webdriver
from selenium.webdriver.common.by import By
option = webdriver.ChromeOptions()
# 指定chrome存储路径的二进制形式
option.binary_location='D:\Chrome\Google\Chrome\Application\chrome.exe'
driver = webdriver.Chrome(options=option)
# r是告知字符串内无转义字符
url = r'D:\个人\学习资料\黑马程序员\Web自动化\web自动化_day01_课件+笔记+资料+代码\02_其他资料\注册实例.html'
# 打开url对应的网页
driver.get(url)
# a标签精确匹配,定位到超链接内容为'注册A网页'的地方
# ele = driver.find_elements(by=By.LINK_TEXT,value='注册A网页')
# a标签模糊匹配,定位到所有超链接内容包含'注册'的地方
ele = driver.find_elements(by=By.PARTIAL_LINK_TEXT,value='注册')
# 选择第二个定位到的超链接并点击
ele[1].click()
# 线程暂停3秒
sleep(3)
# 浏览器关闭
driver.quit()

2.1 XPath定位

XPath是xml path的简称。在html页面中,各组件都有自己的层级结构,通过类似路径的方式定位到组件

如何在Chrome中查找和验证XPath

  1. 通过绝对路径进行定位,以 /html 开头

    image-20231031154057079
  2. 通过相对路径进行定位,以为 // 开头【后续分隔依然是/】

    image-20231031154840149
  3. 路径 + 属性 + 逻辑 进行定位

    image-20231031155804262
    # 对应的实现代码
    ele = driver.find_elements(by=By.XPATH,
                    value="//p[@id='login_user']/input[@name='user-test' and @class='login']")
    
  4. 通过 xpath 内置方法定位

    # 定位到所有标签中文本内容为xxx的元素
    //*[text()='xxx']
    # 定位到属性中含有xxx的元素【这里的attribute是泛指,可以是id,name等】
    //*[contains(@attribute,'xxx')]
    # 属性以xxx开头的元素
    //*[starts-with(@attribute,'xxx')]
    

2.2 css选择器

CSS 是一种标记语言,用于控制元素的显示样式,在 css 标记语言中找元素使用 css 选择器,极力推荐使用,查找元素的效率比 Xpath 高,语法比 Xpath 更简单

  1. id 选择器(前提:元素是必须有 id 属性)

    // 定位到id值为user的元素
    #user
    
    # 将name属性为user的第一个元素赋值为admin
    ele = driver.find_elements(by=By.CSS_SELECTOR,value="[name='user']")
    ele[0].send_keys('admin')
    
  2. class 选择器(前提:元素是必须有 class 属性)

    // 定位到class值为group的元素
    .group
    
  3. 元素选择器

    // 定位到input标签的元素
    input
    
  4. 属性选择器

    // 定位到name属性为admin的元素【任意属性都可以使用这种方法进行定位】
    [name='admin']
    // input标签中type属性以p字母开头的元素
    input[type^='p']
    // input标签中type属性以p字母结束的元素
    input[type$='p']
    // input标签中type属性包含p字母的元素
    input[type*='p']
    
  5. 层级选择器

    // 定位到严格在p下一层的input元素
    p>input
    // 定位到p下方的input【只要在下方即可】
    p input
    

3. 浏览器常用API

# 最大化浏览器
driver.maximize_window() 
# 设置浏览器大小 单位像素
driver.set_window_size(w, h) 
# 设置浏览器位置
driver.set_window_position(x, y) 
# 后退操作
driver.back() 
# 前进操作
driver.forward()
# 刷新操作
driver.refresh() 
# 关闭当前主窗口(主窗口:默认启动哪个界面,就是主窗口)
driver.close() 
# 关闭由driver对象启动的所有窗口
driver.quit() 
# 获取当前页面title信息
driver.title 
# 获取当前页面url信息
drive.current_url 
  • driver.title 和 driver.current_url 没有括号,一般为判断上步操作是否执行成功

  • driver.maximize_window() 一般为我的前置代码,在获取 driver 后,直接编写最大化浏览器

  • driver.close() 与 driver.quit() 区别

    如果当前只有 1 个窗口,close 与 quit 没有任何区别

    • close():关闭当前主窗口
    • quit():关闭由 driver 对象启动的所有窗口

4. 元素信息操作API

获取各组件属性值相关API,如获取id,name等属性

# 获取元素文本
ele.text
#获取元素大小  
ele.size
# 获取元素id属性值
ele.get_attribute("id")
# 判断元素是否可见
ele.is_displayed()
# 判断元素是否可用
ele.is_enabled()
# 判断元素是否被选中
ele.is_selected()
  • text 和 size 调用时 无括号
  • get_attribute 一般应用场景:判断一组元素是否为想要的元素或者判断元素属性值是否正确
  • is_displayed、is_enabled、is_selected,在特殊应用场景中使用

5. 鼠标操作API

通过鼠标操作API模拟测试鼠标的各种效果

双击
# 鼠标事件对应的方法在哪个类中ActionChains类中
from selenium.webdriver.common.action_chains import ActionChains
action = ActionChains(driver)
# 所有操作均需经过perform()方法才能展示效果,当需要模拟多步操作时将perform()放在最后执行
# 右击
action.context_click(ele).perform()
# 双击
action.double_click(ele).perform()
# 拖拽【source是需要拖拽的组件,target是目标位置组件】
action.drag_and_drop(source,target).perform()
# 根据偏移量拖拽
action.drag_and_drop_by_offset(source,xoffset,yoffset)
# 悬停
action.move_to_element(ele).perform()

6. 键盘操作API

from selenium.webdriver.common.keys import Keys
# 删除键
ele.send_keys(Keys.BACK_SPACE)
# 空格键
ele.send_keys(Keys. SPACE)
# 制表键
ele.send_keys (Keys.TAB)
# 回退键
ele.send_keys(Keys.ESCAPE)
# 回车键
ele.send_keys(Keys.ENTER)
# 全选
ele.send_keys(Keys.CONTROL , 'a')
# 复制
ele.send_keys(Keys.CONTROL , 'c')

7. 元素等待

由于电脑配置或网络原因,在查找元素时,元素代码未在第一时间内被加载出来,而抛出未找到元素异常。元素在第一次未找到时,元素等待设置的时长被激活,如果在设置的有效时长内找到元素,继续执行代码,

7.1 隐式等待

设置后对所有组件都会等待

# 找不到组件时等待10秒
driver.implicitly_wait(10)

7.2 显示等待

只等待指定组件

from selenium.webdriver.support.wait import WebDriverWait
# 每隔0.5秒尝试寻找一次id值为d的组件,共持续10秒
wait_rule = WebDriverWait(driver,timeout=10,poll_frequency=0.5)
# until()参数为匿名函数,其中x是创建等待规则时传入的driver类
# 按照wait_rule的规则寻找id为user的组件
ele = wait_rule.until(lambda x:x.find_element_by_id("#user"))
# 设置组件值
ele.send_keys("admin")

8. 下拉框API

操作下拉框对应API,用 css 选择器配合 click 也可达到同样效果,使用 Select 则不需要使用 click

from selenium.webdriver.support.select import Select
# ele是下拉框对应的标签<select>,定位至select标签
s = Select(ele)
# 通过下标定位【从1开始】
s.select_by_index() 
# 通过value属性定位
s.select_by_value() 
# 通过下拉框文本定位
s.select_by_visible_text() 

9. 弹窗处理

如果页面由弹出框【alert 警告框,confirm 确认框,prompt 提示框】,不处理,接下来的操作将不生效。

无论以上哪个对话框,都可以使用取消、同意,因为调用的是后台的事件,与页面显示按钮数量无关

# 获取对话框对象,统一转换为此对象处理
al = driver.switch_to.alert
# 获取对话框文本
al.text 
# 对话框确认按钮
al.accept() 
# 对话框取消按钮
al.dismiss() 

10. 滚动条

在 web 自动化中有些特殊场景,如:滚动条拉倒最底层,指定按钮才可用,Selenium 中没有提供直接操作滚动条的API,但是可以通过执行 JS 语句完成此项工作

# 0是左边距【水平滚动条】,10000是上边距【垂直滚动条】,越界时拉到底
# 此处js作用是将滚动条垂直拉到底
js = "window.scrollTo(0,10000)"
# 执行js方法
driver.execute_script(js)

11. 同一页面内窗口切换

常用的 frame 表单有两种:frame、iframe

# 使用css语法可以定位至对于frame位置【可以使用name、id、iframe元素】
driver.switch_to.frame("id\name\element")
# 操作完毕后需要切换为主目录才能再次操作其余frame
driver.switch_to.default_content()

12. 多窗口切换

多个浏览器窗口间切换

# 获取当前主窗口句柄
driver.current_window_handle 
# 获取当前由driver启动所有窗口句柄
driver.window_handles
# 切换至最开启的窗口
driver.switch_to.window(driver.window_handles[-1]) 

13. 截图

# 截图并保存至指定位置【png格式】
driver.get_screenshot_as_file(imgepath)
# 使用时间戳对事件命名
driver.get_screenshot_as_file("../image/%s.png"%(time.strftime("%Y_%m_%d %H_%M_%S")))

14. 验证码

验证码通常是为了放置恶意请求,因此程序不好直接控制,在测试环境下,通常对于验证码有如下策略

  1. 去掉验证码(项目在测试环境、公司自己的项目)

  2. 设置万能验证码(测试环境或线上环境,公司自己项目)

  3. 使用验证码识别技术 (由于现在的验证码千奇百怪,导致识别率太低)

  4. 使用cookie解决【推荐】

    部分网站是动态生成的cookie则无法使用这种方法

    • cookie 由服务器生成,标识一次对话的状态(登录的状态)
    • 浏览器自动记录 cookie,在下一条请求时将 cookie 信息自动附加请求
# 获取所有的cookie
driver.get_cookies() 
# 设置cookie
driver.add_cookies(字典) 

15. PO模式

PO(Page Object),页面对象,将自动化涉及的页面或模块封装成对象,其主要有以下两个好处:

  1. 代码复用性
  2. 便于维护(脚本层和业务分类),如果元素信息变化了也不用修改脚本

PO 模式通常会将代码分为以下几个部分:

  • Base 层

    存放所有页面公共方法,如定位到某个元素的方法

  • Page 层

    基于页面或模块单独封装当前页面要操作的对象,是具体的业务操作,如输入用户名密码

  • Script 层

    脚本层 + UnitTest,获取浏览器对象,调用 Page 层的方法进行操作

案例:使用 PO 模式测试网站登录功能

image-20240315151022422 image-20240315151440813

base.py

from selenium.webdriver.support.wait import WebDriverWait
class Base:
    # 在获取浏览器对象后才有后续一系列操作
    def __init__(self,driver):
        self.driver = driver
    # 切换浏览器窗口
    def base_switch_win(self,index=-1):
        # -1代表最新打开的窗口,0为主窗口
        self.driver.switch_to.window(self.driver.window_handles[index])
    # 查找元素【loc为(By.xxx,查询目标)】
    def base_find(self,loc,timeout=10,frequency=0.5):
        # 显式等待10秒,每隔0.5秒问询一次
        return WebDriverWait(self.driver,timeout,frequency).until(lambda x:x.find_element(*loc))
    # 输入方法
    def base_input(self,loc,value):
        ele = self.base_find(loc)
        ele.clear()
        ele.send_keys(value)
    # 点击方法
    def base_click(self,loc):
        self.base_find(loc).click()
    # 获取文本值
    def base_text(self,loc):
        ele = self.base_find(loc)
        return ele.text

page_login.py

from ..base.base import Base
from selenium.webdriver.common.by import By
# 参数定位方式
keywords = By.CSS_SELECTOR,'#keywords'
password = By.CSS_SELECTOR,'#password'
login = By.CSS_SELECTOR,'#login-btn'
nickname = By.CSS_SELECTOR,'.a-link1'

class Page(Base):
    # 切换到最新的窗口
    def page_switch(self,index):
        self.base_switch_win(index)
    # 输入用户名
    def page_insert_keywords(self,value):
        self.base_input(keywords,value)
    # 输入密码
    def page_insert_password(self,value):
        self.base_input(password, value)
    # 点击登录按钮
    def page_click_login(self):
        self.base_click(login)
    # 获取登录成功后的用户名
    def page_get_nickname(self):
        return self.base_text(nickname)
    # 封装登录业务
    def page_login(self,username,pwd):
        self.page_insert_keywords(username)
        self.page_insert_password(pwd)
        self.page_click_login()

test01_login.py

import time
import unittest
from selenium import webdriver
from ..page.page_login import Page
from parameterized import parameterized
class TestLogin(unittest.TestCase):
    # 每个方法执行前的操作
    def setUp(self) -> None:
        option = webdriver.ChromeOptions()
        # 设置浏览器启动地址
        option.binary_location = 'D:\Chrome\Google\Chrome\Application\chrome.exe'
        # 获取浏览器实例对象driver
        self.driver = webdriver.Chrome(options=option)
        # 最大化窗口
        self.driver.maximize_window()
        # 打开浏览器
        self.driver.get('http://xxxxx')
        # 获取登录页面示例对象
        self.login = Page(self.driver)
    # 每个方法执行后的操作
    def tearDown(self) -> None:
        self.driver.quit()
    # 参数化管理数据
    @parameterized.expand((('123xxxxx','a1xxxxxxx'),))
    def test001_login(self,keywords,password):
        # 执行登录操作
        self.login.page_login(keywords,password)
        # 休眠一段时间等待新页面跳出
        time.sleep(5)
        # 切换浏览器窗口
        self.login.page_switch(index=-1)
        # 获取关键信息
        name = self.login.page_get_nickname()
        # 断言
        self.assertEqual(keywords,name)
image-20240315153206684

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/462848.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android VINF

周末搞这玩意欲仙欲死&#xff0c;没办法只有看看。VINTF是供应商接口对象&#xff08;VINTF 对象&#xff09;&#xff0c;准确的说&#xff0c;这个是属于兼容性矩阵概念。。。有点想起了以前看过的一个电影&#xff0c;异次元杀阵。。。下面是谷歌官方的图。 本质上其实就是…

【分布式websocket 】前端vuex管理客户端消息crud!使用localStorage来存储【第19期】

前言 聊天系统客户端是要存储消息的&#xff0c;因为所有所有的历史消息都从服务器拉的话一方面服务器压力大&#xff0c;另一方面也耗费用户流量。所以客户端存储消息是势在必行的。如何存储呢上一篇文章也写了&#xff0c;大概就是浏览器的话是localStorage或者IndexedDB。然…

解决Linux中Eclipse启动时找不到Java环境的问题

按照报错的意思是没有在/usr/local/eclipse/jre/bin/java下找到java环境&#xff0c;我检查了一下eclipse的目录结构发现在/usr/local/eclipse没有jre/bin/java&#xff0c;我的想法是自己建对应文件夹然后软连接到我的java环境 cd /usr/local/eclipse sudo mkdir jre cd jre s…

基于Struts开发物流配送(快递)管理系统

开发工具&#xff1a;EclipseJdkTomcatMySQL数据库

使用Lua编写Wireshark解析ProtoBuf插件

文章目录 Wireshark Protobuf Lua-dissectorStep 1: 获取 WiresharkStep 2: 配置ProtoBuf相关设置添加ProtoBuf查找路径 Step 3 运行和调试Lua代码1. 添加Lua脚本2. 运行和调试 Step 4: 写Lua Dissector代码 :)Step 5(Optional): Decode AsGithub工程地址 Wireshark Protobuf L…

最新潮乎盲盒系统源码,附搭建教程

搭建方法 宝塔创建网站&#xff0c;上传后端程序到根目录&#xff0c;在.env修改数据库账号密码 上传数据库&#xff0c;伪静态thinkphp 运行目录public PHP扩展安装下面的 禁用函数先禁用下面那个&#xff0c;就可以了 前端是uniapp 后台admin 禁用函数putenv、 扩展fileinfo…

python问题:vscode切换环境,pip安装库网络错误

python问题&#xff1a;vscode切换环境&#xff0c;pip安装库网络错误 vscode切换环境pip安装库网络错误 记录一下遇见的python问题。 vscode切换环境 在vscode上面的搜索框输入 > select interpreter然后选择需要的环境。 pip安装库网络错误 用requirements.txt来安装…

【目标检测】原始的 YOLOv1 网络结构(GoogLeNet 作为 backbone 的实现)

现在看网上的很多 YOLOv1 的代码实现&#xff0c;基本都是使用新的 backbone&#xff0c;例如 ResNet 或者 VGG 来实现的&#xff0c;因为这些后面的通用的 backbone 可能比较方便的获得预训练模型&#xff0c;不需要从头开始训练。 但是我就是想看一下&#xff0c;一开始 YOL…

IntelliJ IDEA 面试题及答案整理,最新面试题

IntelliJ IDEA中的插件系统如何工作&#xff1f; IntelliJ IDEA的插件系统工作原理如下&#xff1a; 1、插件架构&#xff1a; IntelliJ IDEA通过插件架构扩展其功能&#xff0c;插件可以添加新的功能或修改现有功能。 2、安装和管理&#xff1a; 通过IDEA内置的插件市场下载…

游戏服务端配置“热更”及“秒启动”终极方案(golang/ygluu/卢益贵)

游戏服务端配置“热更”及“秒启动”终极方案&#xff08;golang/ygluu/卢益贵&#xff09; 关键词&#xff1a;游戏微服务架构、游戏服务端热更、模块化解耦、golang 一、前言 众所周知&#xff0c;游戏服务端配置信息热更有几大问题&#xff08;非lua架构&#xff09;&…

电脑那个部件坏了或者是哪个软件需要修复来看价钱

电脑维修价格表是多少&#xff1f; 价格取决于计算机的哪个部分损坏或哪个软件需要修复。 由于电脑中的部件非常多&#xff0c;而且会以各种奇怪的方式出现问题&#xff0c;下面我们就来看看具体的充电方法。 电脑维修价格表&#xff1a; 1. 重新安装系统。 安装XP系统通常需…

Tomcat Session 集群 ---------会话保持

一、 负载均衡、反向代理 环境搭建&#xff1a; nginx服务器192.168.246.7 tomcat 1服务器192.168.246.8 tomcat 2服务器192.168.246.9 7-1 nginx服务器搭建 [rootzzcentos1 ~]#systemctl stop firewalld [rootzzcentos1 ~]#setenforce 0 [rootzzcentos1 ~]#yum install …

Visual Studio配置libtorch(cuda安装一步到位)

Visual Studio配置libtorch visual Studio安装cuDNN安装CUDAToolkit安装libtorch下载Visual Studio配置libtorch(cuda版本配置) visual Studio安装 visual Studio点击安装 具体的安装和配置过程这里就不进行细讲了&#xff0c;可以参考我这篇博客Visual Studio配置OpenCV(保姆…

openCV实现拖拽虚拟方块

一、项目效果&#xff1a; 二、核心流程&#xff1a; openCV读取视频流、在每一帧图片上画一个矩形。使用mediapipe获取手指关键点坐标。根据手指坐标位置和矩形的坐标位置&#xff0c;判断手指点是否在矩形上&#xff0c;如果在则矩形跟随手指移动。 三、代码流程&#xff1…

基于SpringBoot框架实现的B2B平台的医疗病历交互系统

采用技术 基于SpringBoot框架实现的B2B平台的医疗病历交互系统的设计与实现~ 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBootMyBatis 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 页面展示效果 管理员角色 医院管理 医院注册 医院文…

C语言—打印如图矩阵

输出矩阵 在一个二维数组中形成并输出如下矩阵: #include <stdio.h> main() { int i,j,a[5][5];for(i0;i<4;i)for(j0;j<4;j)if(i<j) a[i][j]1;else a[i][j]i-j1;for(i0;i<4;i){ for(j0;j<4;j)printf("%d ",a[i][j]);printf("…

介绍一款鼠标无边界软件

"Mouse without Borders" 是一款由微软开发的免费工具&#xff0c;旨在帮助用户在多台计算机之间实现无缝的鼠标和键盘共享。通过 Mouse without Borders&#xff0c;用户可以在一个主控制台上控制多台计算机&#xff0c;就像操作一个大型虚拟桌面一样。 这个工具可…

zookeeper基础学习之六: zookeeper java客户端curator

简介 Curator是Netflix公司开源的一套zookeeper客户端框架&#xff0c;解决了很多Zookeeper客户端非常底层的细节开发工作&#xff0c;包括连接重连、反复注册Watcher和NodeExistsException异常等等。Patrixck Hunt&#xff08;Zookeeper&#xff09;以一句“Guava is to Java…

数字IC实践项目(9)—SNN加速器的设计和实现(tiny_ODIN)

数字IC实践项目&#xff08;9&#xff09;—基于Verilog的SNN加速器 写在前面的话项目整体框图完整电路框图 项目简介和学习目的软件环境要求 Wave&CoverageTiming&#xff0c;Area & Power总结 写在前面的话 项目介绍&#xff1a; SNN硬件加速器是一种专为脉冲神经网…

nanodet笔记

nanodet简单笔记 这里简单记录下nanodet的结构. 网络stride8,16,32的feature 经过共享卷积处理后cat在一起再transpose,直接产生shape为(B, n_grid, n_class8*4),其中B为batchsize, n_grid为feature map上点的个数, 4:表示top,bottom, left, right 4个值,每个值使用8个bin的概…