介绍
Selenium 是一个用于 Web 应用程序测试的工具。它提供了一个 API,让开发者可以使用多种编程语言来编写测试脚本,从而模拟用户在浏览器中的操作。Selenium 可以用来测试 Web 应用程序的功能、性能和兼容性等方面。它支持多种浏览器,包括 Chrome、Firefox、Safari 和 Edge 等。Selenium 的主要优点是它可以在不同的操作系统和浏览器上运行测试脚本,并且可以自动化执行测试用例,从而提高测试效率和准确性。
原理
Selenium 的原理是通过模拟用户在浏览器中的操作,来测试 Web 应用程序的功能。Selenium 提供了一个 WebDriver API,让开发者可以使用多种编程语言来编写测试脚本。测试脚本可以发送 HTTP 请求、填写表单、点击按钮、滚动页面等操作,就像用户在浏览器中手动操作一样。Selenium 会将这些操作转化为浏览器可以理解的指令,并在浏览器中执行。在执行测试脚本的过程中,Selenium 会记录浏览器的状态和响应,并将它们与预期的结果进行比较。如果结果与预期不符,测试脚本就会失败,并生成相应的错误报告。简单来说:python调用selenium,selenium调用浏览器驱动,浏览器驱动控制浏览器。
总结:
- 自动化程序调用Selenium 客户端库函数(比如点击按钮元素)
- 客户端库会发送Selenium 命令给浏览器的驱动程序
- 浏览器驱动程序接收到命令后 ,驱动浏览器去执行命令
- 浏览器执行命令
- 浏览器驱动程序获取命令执行的结果,返回给我们自动化程序
- 自动化程序对返回结果进行处理
环境安装
- 安装selenium
pip install selenium==4.3.0
- 安装浏览器驱动,chrome示例:1. 需要下载 Chrome 浏览器驱动程序,官方网站https://sites.google.com/chromium.org/driver/2. 需要将 Chrome 浏览器的可执行文件(chrome.exe)的路径添加到系统的环境变量 PATH 中3. cmd中验证 Chrome 浏览器驱动是否已经安装成功
chromedriver --version
验证环境
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get('www.baidu.com')
driver.maximize_window()# 点击百度一下
driver.find_element(By.ID,'su').click()
driver.quit()
元素定位
- WebElement对象find_element()系列:用于定位单个的页面元素,返回一个 WebElement 类型的对象 find_elements()系列:用于定位一组页面元素,获取到的是一组列表,返回一个 WebElement 类型的对象, 如果没有符合条件的元素, 返回空列表, 如果没有符合条件的元素, 抛出 NoSuchElementException 异常
- 元素定位方式 8大定位方式,id 、class、text、tag、link 、partial link 、xpath、css,常用的id、text、xpath、class、link- find_element(By.ID,‘XX’) 最为方便且唯一,但有可能不存在,也可能动态生成。- find_element(By.NAME,‘xx’) 定位到的标签不一定是唯一的。- find_element_by(By.CLASS_NAME,‘xx’) 可能受JS影响动态变化,不一定是唯一的。- find_element(By.TAG_NAME,‘xx’) 标签名定位,定位到的标签不一定是唯一的。# 选择标签(搜索按钮),执行点击操作- find_element(By.LINK_TEXT,‘XX’) 根据链接文本全匹配进行精确定位。- find_element(By.PARTIAL_LINK_TEXT,‘XX’) 根据链接文本模糊匹配进行定位。link表示包含有属性href的标签元素,如:linktext可以通过LINK_TEXT进行定位。- find_element(By.XPATH,‘XX’) xpath表达式来完成定位,可以准确定位任何元素。- find_element(By.CSS_SELECTOR,‘XX’) css选择器来完成定位,可以准确定位任何元素,但需要熟练掌握css选择器
元素的可见性
driver = webdriver.Chrome()
driver.get('https://www.baidu.com/')
driver.implicitly_wait(10)
el = driver.find_element(By.ID,"su")print(el.is_displayed())# 元素是否可见print(el.is_enabled())# 按钮是否启用print(el.is_selected())# 复选框是否选中了
Frame里面元素定位
先切换至driver.switch_to.frame里面,再进行定位,完成操作再driver.switch_to.default_content()跳出来
# 创建一个浏览器驱动对象
driver = webdriver.Chrome()# 跳转到利url页面
driver.get('https://www.126.com/')# 先跳转到iframe
driver.switch_to.frame(driver.find_element(By.XPATH,"//iframe[starts-with(@id,'x-URS-iframe')]"))
driver.find_element(By.NAME,"email").send_keys("123")# 跳出iframe
driver.switch_to.default_content()# 跳出iframe后可操作iframe之外的元素
value = driver.find_element(By.LINK_TEXT,"注册VIP").text
print(value)
多窗口,打开一个新的窗口链接
1)首先获取所有窗口的句柄hand = driver.window_handles
2)切换至最后一个窗口driver.switch_to.window(hand[-1])
3)再操作页面元素
# 打开新的窗口
driver.find_element(By.XPATH,"//*[@id='s-hotsearch-wrapper']/div/a[1]/div").click()# 获取全部窗口的句柄,hand是一个list
hand = driver.window_handles
# 跳转到最后一个窗口,即新打开的页面
driver.switch_to.window(hand[-1])
alert弹窗
切换至driver.switch_to.alert,再操作accept、dismiss、text
alert = driver.switch_to.alert
alert.accept()
alert.dismiss()
alert.send_keys('')
value = alert.text
print(value)
当前元素高亮显示
这个其实就是利用javaScript去修改当前元素的边框样式来到达高亮显示的效果
不可输入的disable属性去掉
execute_script(X)执行JS代码,X代表要执行的JS代码
# 某输入框不可以输入,使用js将disable属性去掉,就可以直接输入了
driver = webdriver.Chrome()
driver.get('https://www.baidu.com')
driver.implicitly_wait(10)# document.getElementById('myElementId')---JavaScript 中用于获取文档元素后移除disable属性
driver.execute_script("document.getElementById('').removeAttribute('disable')")# JavaScript 中用于获取文档元素后改变元素style,display = None的情况可以定位
driver.excute_script("document.getElementById('').style.display=''")
浏览器操作
# 浏览器前进一页
driver.navigate().forward();# 浏览器后退
driver.navigate().back();# 浏览器刷新
driver.navigate().refresh();
获取页面内容
title页面标题
page_source 页面源码
current_url页面连接
text标签内文本
from selenium import webdriver
from selenium.webdriver.common.by import By
# 启动并打开指定页面
driver = webdriver.Chrome()
driver.get("http://www.csdn.net")# 获取标题
title = driver.title
print(title)# 获取源代码
source_code = driver.page_source
print(source_code)# 获取页面链接
url = driver.current_url
print(url)# 获取标签内文本
text = driver.find_element(By.XPATH,'/html/body/div[1]/div/div/div/div[2]/div/div/button/span').text
print(text)# 关闭页面
browser.quit()
调整浏览器窗口尺寸
maximize_window()窗口最大化。
minimize_window()窗口最小化。
set_window_size(width,height)调整窗口到指定尺寸。
获取标签元素的属性值(复选框)
get_attribute(“XX”)获取标签属性值,XX为标签属性名。
type_value = driver.find_elements(By.TAG_NAME,'input')# 通过type属性的值来定位元素,并进行选取for type_value in tag_input:# 输出input标签的name属性的值:print(type_value.get_attribute("name"))# 对复选框进行选取操作if type_value.get_attribute("type")=="checkbox":
type_value.click()
time.sleep(2)
下拉列表
Select("XX)判断标签元素XX是否为下拉列表元素,是返回Select对象,不是报错
select_by_value(“XX”)通过下拉列表value属性的值XX选择选项
select_by_visible_text(“XX”)通过下拉列表文本内容XX选择选项
select_by_index(N)或options[N].click()通过下拉列表索引号N选则选项,从0 开始
options下拉列表内options标签
# 定位下拉列表标签,并创建下拉列表对象
select = Select(driver.find_element(By.TAG_NAME,"select"))# 通过value属性选择选项
select.select_by_value("Python")
sleep(2)# 通过文本内容选择选项
select.select_by_visible_text("C++")
sleep(2)# 通过选项索引号选择选项
select.select_by_index(0)# 等同于 select.options[0].click()
sleep(2)# 通过options属性循环选取for i in select.options:
i.click()
sleep(2)
鼠标操作
move_to_element(X)鼠标悬停,X代表定位到的标签
double_click(X)双击
context_click(X)右击
from time import sleep
# 导入selenium包from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
# 启动并打开指定页面
driver = webdriver.Chrome()
driver.get("https://www.csdn.net")
sleep(2)# 创建ActionChains对象
action = ActionChains(driver)# 定位标签并将鼠标移入,并呈现移入结果
tag = driver.find_element(By.XPATH,'//div/a[@class="btn-write-new"]')# perform() 执行所有存储在ActionChains()类中的行为,做最终的提交
action.move_to_element(tag).perform()
sleep(3)
tag = driver.find_element(By.CSS_SELECTOR,'.blog-nav-box')
action.move_to_element(tag).perform()
sleep(2)
driver.find_element(By.LINK_TEXT,"数学").click()# 关闭浏览器
sleep(2)
browser.quit()
键盘操作
全选、剪切、粘贴、回退一格
from selenium.webdriver import ActionChains, Keys
input_text = driver.find_element(By.XPATH,'//*[@id="toolbar-search-input"]')
input_text.send_keys("selenium")# 全选
input_text.send_keys(Keys.CONTROL,"a")# 剪切
input_text.send_keys(Keys.CONTROL,'x')# 粘贴
input_text.send_keys(Keys.CONTROL,'v')# 回退一格
input_text.send_keys(Keys.BACK_SPACE)
浏览器窗口截图
# 代表文件保存地址及文件名、格式。只写文件名保存至当前路径,若写路径,则路径必须存在。
browser.get_screenshot_as_file("csdn.png")
元素等待
sleep()强制等待 始得线程强制处于睡眠状态
driver.implicitly_wait()隐形等待 ,设置的时全局等待,调用一次就够了
webdriverwait()显性等待 等待方式expected_conditions 特定的元素都设置自己的等待方式进行等待
常用显示等待
解决隐式等待无法解决的问题:元素可以找到,使用点击等操作,出现报错。可能会导致脚本执行速度整体变慢
原因:页面元素加载是异步加载过程,通常 xml 会先加载完成,相应的元素属性后加载元素存在与否是由 xml 决定,元素的交互是由属性决定隐式等待只关注元素能不能找到,不关注元素能否点击或者进行其他的交互
显示等待用到的两个类——WebDriverWait、expected_conditions
WebDriverWait的用法
方法说明: WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)
参数说明:
● driver:浏览器驱动。
● timeout:最长超时时间,默认以秒为单位
● poll_frequency:检测的间隔步长,默认是0.5s
● ignored_exceptions:超时后的抛出的异常信息,默认抛出NoSuchElementException异常
WebDriverWait的until()和until_not()方法
方法说明:
● until( method, message=‘’) :当某元素出现或什么条件成立则继续执行
● until_not(method, message=‘’) :当mou元素消失或什么条件不成立则继续执行。
参数说明:
● method:在等待时期,每隔一段时间(init中的poll_frequency)调用这个传入的方法,知道返回值不是False。
● message:如果超时,抛出TimeoutException,将message传入异常
expected_conditions 类
● presence_of_element_located:判断元素是否被加载到dom树里,并不代表元素一定可被定位
用法:WebDriverWait().until(expected_conditions.presence_of_element_located(元素对象))
● visibility_of_element_located:判断某个元素是否可见,可见代表元素非隐藏,并且元素的宽和高都不等于0.
用法:WebDriverWait().until(expected_conditions.visibility_of_element_located(locator))
● element_to_be_clickable:判断每个元素是否可点击
用法:WebDriverWait().until(expected_conditions.element_to_be_clickable(locator))
示例1
visibility_of_element_located判断某个元素是否可见. 可见代表元素非隐藏,并且元素的宽和高都不等于0
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions
classTest001:deftest_001(self):
driver = webdriver.Edge()
driver.implicitly_wait(10)
driver.get('https://www.baidu.com/')
driver.maximize_window()# 元组,元素定位方式和定位值
kw_el =(By.ID,'kw')# 使用显示等待,用visibility_of_element_located去判断元素是否加载好得到一个webelement对象
WebDriverWait(driver,10).until(expected_conditions.visibility_of_element_located(kw_el))# 百度搜索框输入“selenium”
driver.find_element(*kw_el).send_keys('selenium')
driver.quit()
示例2
until中使用lambda表达式来进行查询元素
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
classTest001:deftest_case001(self):
driver = webdriver.Edge()
driver.implicitly_wait(10)
driver.get('https://www.baidu.com/')
driver.maximize_window()# 搜索框输入“selenium”
kw_el =(By.ID,'kw')
WebDriverWait(driver,10).until(lambda x: x.find_element(*kw_el))
driver.find_element(*kw_el).send_keys('selenium')
driver.quit()
PO设计模式
简单来说就是用class去表示被测页面。在class中定义页面上的元素和一些该页面上专属的方法。
按照Po模式搭建自动化框架
搭建框架使用的技术是selenium + pytest 。
将框架分为层:
common层(公共层:basepage[基础操作封装]、my_logger[日志分装])、conf(配置层:ini文件、yaml文件)
report(日志输出层)、
pageobject(页面对象)、
pagelocators(页面定位)、
testcases(测试用例)、
testdatas(测试数据)
POM主要有以下优点:
- 把web ui对象从测试脚本分离,业务代码和测试脚本分离。
- 每一个页面对应一个页面类,页面的元素写到这个页面类中。
- 页面类主要包括该页面的元素定位,和这些元素相关的业务操作代码封装的方法。
- 代码复用,从而减少测试脚本代码量。
- 层次清晰,同时支持多个编写自动化脚本开发,例如每个人写哪几个页面,不影响他人。
版权归原作者 小徐的糖 所有, 如有侵权,请联系我们删除。