python自动化web自动化:2.web自动化工具selenium讲解
Posted new nm个对象
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python自动化web自动化:2.web自动化工具selenium讲解相关的知识,希望对你有一定的参考价值。
一.selenium简介
1.什么是selenium
Selenium是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome,Opera,Edge等。
2.selenium三大组件
-
WebDriver:是selenium提供的一个API,用于操作浏览器。
-
IDE:是selenium提供的一个插件,可以录制用户的操作
-
Grid:是selenium分布式的工具,实现在多个浏览器操作。使用Grid可以轻松实现用例的分布式执行。
-
我们编写自动化主要使用WebDriver来实现,我们后面所指的selenium默认也是WebDriver
3.selenium的工作原理
4.selenium环境准备
- 在python中安装selenium
pip install selenium
- 配置浏览器驱动
下载driver:https://npm.taobao.org/mirrors/,选择对应的浏览器driver已经对应的版本,下载zip包。
将浏览器driver配置待环境变量,或者使用driver时指定路径。
5.selenium编写测试用例的步骤
(1)导入依赖
(2)生成driver
(3)执行测试步骤
(4)断言
import time
from selenium import webdriver # 导入selenium
# 使用webdriver,生成一个对应浏览器的driver。该driver提供了许多操作浏览器的API。
# 使用executable_path来指定chromedriver路径,如果将chromedriver.exe配置在了环境变量中,则不需要指定。
driver = webdriver.Chrome(executable_path='./etc/chromedriver.exe')
# 使用driver的api执行测试步骤
driver.get('https://www.baidu.com/') # 打开浏览器
driver.find_element_by_id('kw').send_keys('selenium') # 定位元素,并输入内容
driver.find_element_by_id('su').click() # 定位并点击元素
time.sleep(3)
# 断言
assert 'selenium' in driver.title
二.selenium的webdriver的常用API
1.webdriver访问网站API
from selenium import webdriver # 导入selenium
driver = webdriver.Chrome(executable_path='./etc/chromedriver.exe')
driver.get('https://www.baidu.com/') # 访问网站
2.元素定位API
selenium中提供了八种元素定位的方式。
(1)id定位
通过id属性来定位元素,定位唯一.
格式:
# 找到界面上id为'kw'的元素,以下两种方式效果一样.
1.driver.find_element_by_id('kw')
2.driver.find_element(By.ID,'kw')
(2)name定位
通过 name 属性来定位元素,定位唯一
# 找到界面上name为'sss'的单个元素,以下两种方式效果一样.
driver.find_element_by_name('sss')
driver.find_element(By.NAME,'sss')
# 找到界面上name为'sss'的所有元素,以下两种方式效果一样.
driver.find_elements_by_name('sss')
driver.find_elements(By.NAME,'sss')
(3)class name 定位
通过元素的 class 属性来定位元素,name和id在所有元素中是唯一的
# 找到界面上class为'sss'的单个元素,以下两种方式效果一样.
driver.find_element_by_class_name('sss')
driver.find_element(By.CLASS_NAME,'sss')
# 找到界面上class为'sss'的所有元素,以下两种方式效果一样.
driver.find_elements_by_class_name('sss')
driver.find_elements(By.CLASS_NAME,'sss')
(4)link_text定位
通过链接文本信息来定位,只能用于a标签
driver.find_element_by_link_text('内容')
driver.find_element(By.LINK_TEXT,'内容')
(5)partial link text 定位
对 link text 定位的补充,有些文本链接比较长,或者这些文本链接其中有一部分文本信息是动态生成的,这个时候,可以选择文本链接的一部分进行定位,只要这部分信息可以唯一的标识这个链接。
driver.find_element_by_partial_link_text('内容')
driver.find_element(By.PARTIAL_LINK_TEXT,'内容')
(6)tag 定位
通过元素的标签名来定位元素
driver.find_element_by_tag_name('内容')
driver.find_element(By.TAG_NAME,'内容')
(7)xpath定位
格式:
1.driver.find_element_by_xpath('xpath路径')
2.driver.find_elements(By.XPATH,'xpath路径')
xpath详解:
练习:
//div[@id="wraf"] #定位到id=wraf的div元素
//*[@id="wraf"] #定位到id=wraf的元素,*表示类型不限
//*[@id="wraf"]/* #定位到id=wraf的元素的所有子集元素,*表示类型不限
//*[@id="wraf"]/div #定位到id=wraf的元素的所有子集div元素
//*[@id="wraf"]//a #定位到id=wraf的元素的所有子集以及子集的子集(无论差几级)中的所有的a元素
//*[contains(@id,"kw")] #定位到id包含wraf的元素
//*[text()="wraf"] # 定位到文本内容为wraf的元素
//*[contains(text(),"wraf")] # 定位到文本内容包含wraf的元素
//*[@id="wraf" and @class="asdff"] # 定位id为wraf且class为asdff的元素
(8)css_selector定位
格式:
1.driver.find_element_by_css_selector('css路径')
2.driver.find_element(By.CSS_SELECTOR,'css路径')
css详解:
练习:
#wraf #定位id为wraf的元素
#wraf>div #定位id为wraf的元素的子集中的所有div元素
#wraf a #定位id为wraf的元素的子子孙孙集中的所有a元素
#wraf a:nth-child(2) #定位id为wraf的元素的子子孙孙集中的所有a元素,且这些a元素属于它父级的第二个子元素。
3.鼠标点击:定位元素后.click()
driver.find_element_by_id('su').click()
4.输入内容:定位元素后.send_keys(“内容”)
driver.find_element_by_id('kw').send_keys('自动化测试')
5.清空内容:定位元素后.clear()
element = driver.find_element(By.ID,'kw')
element.send_keys('自动化测试')
sleep(2)
element.clear()
6.退出浏览器
driver.quit()
7.获取页面title
s = driver.title
8.最大化浏览器窗口
driver.maximize_window()
9.等待方式
9.1 页面元素加载顺序
9.2 直接等待
from time import sleep
sleep(3) # 线程休眠3秒
9.3 隐式等待
driver.implicitly_wait(5)
# 在5秒内不断检测元素是否出现,出现就结束等待,执行下一步。如果5秒内没有出现就抛出异常
# 隐式等待是作用在全局的,一般放在setup中
# 隐式等待有一个缺点:因为隐式等待是针对全局的元素而言的,而每个元素的加载时间是不一样的。所以隐式等待的等待时间是不能很好的兼容所有元素。
# 使用隐式等待会有这个bug,就是元素已经出现,但不能被点击。所以导致用例失败。这是因为浏览器加载时,会先加载DOM节点,然后再加载js等静态文件,所以会出现元素已经出现,但无法点击的问题。
9.4 显示等待
格式:
# 在规定的时间内不断的调用方法1,直到方法1返回True,结束等待。超时抛出异常
WebDriverWait(driver驱动,等待时间).until(方法1)
# 在规定的时间内不断的调用方法1,直到方法1返回False,结束等待。超时抛出异常
WebDriverWait(driver驱动,等待时间).until_not(方法1)
until后的方法,selenium中有许多。我们介绍几种常用的:
- expected_conditions.presence_of_element_located----判断某个元素是否被加到了 dom 树里,并不代表该元素一定可见
from selenium import webdriver # 导入依赖
from time import sleep
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
driver = webdriver.Chrome()
driver.get('https://www.baidu.com/')
element = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID,'kw')))
# 显式等待:直到对应的元素出现,就结束等待。并且定位到该元素
element.send_keys('selenium')
-
expected_conditions.visibility_of_element_located-----判断某个元素是否可见. 可见代表元素非隐藏,并且元素的宽和高都不等于 0
-
expected_conditions.presence_of_all_elements_located—判断是否至少有 1 个元素存在于 dom 树中。举个例子,如果页面上有 n 个元素的 class 都是’column-md-3’,那么只要有 1 个元素存在,这个方法就返回 True
-
expected_conditions.text_to_be_present_in_element—判断某个元素中的 text 是否 包含 了预期的字符串
-
expected_conditions.text_to_be_present_in_element_value----判断某个元素中的 value 属性是否包含 了预期的字符串
-
expected_conditions.invisibility_of_element_located----判断某个元素中是否不存在于dom树或不可见
-
expected_conditions.element_to_be_clickable—判断某个元素中是否可见并且是 enable 的,这样的话才叫 clickable
-
expected_conditions.element_to_be_selected—判断某个元素是否被选中了,一般用在下拉列表
10.action接口
10.1 简介
selenium给我们提供了两种操作浏览器控件的actions接口:
10.2 ActionChains
(1).鼠标单击,双击,左键操作
from selenium import webdriver
from selenium.webdriver import ActionChains
import pytest
class TestSelenium:
def setup(self):
self.driver = webdriver.Chrome()
self.driver.get("http://sahitest.com/demo/clicks.htm")
self.driver.implicitly_wait(5)
def teardown(self):
self.driver.close()
def test_selenium(self):
# 定位元素
element_click = self.driver.find_element_by_xpath("//*[@value='click me']")
element_double_click = self.driver.find_element_by_xpath("//*[@value='dbl click me']")
element_right_click = self.driver.find_element_by_xpath("//*[@value='right click me']")
# 创建一个action
action = ActionChains(self.driver)
# 给action添加需要执行的方法
action.click(element_click) # 鼠标左键单击
action.double_click(element_double_click) # 鼠标左键双击
action.context_click(element_right_click) #鼠标右键点击
# 执行action
action.perform()
(2).鼠标移动到某个元素上
from selenium import webdriver
from selenium.webdriver import ActionChains
import pytest
from time import sleep
class TestSelenium:
def setup(self):
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(5)
self.driver.maximize_window() #最大化窗口
def teardown(self):
self.driver.close()
def test_move(self):
self.driver.get("https://www.baidu.com/")
# 定位元素
ele = self.driver.find_element_by_id("s-usersetting-top")
# 创建action
action = ActionChains(self.driver)
# 给action添加操作方法
action.move_to_element(ele) # 移动到元素上,但不点击
# 执行action
action.perform()
(3).拖拽一个元素到另一个元素上
方法一:
from selenium import webdriver
from selenium.webdriver import ActionChains
import pytest
from time import sleep
class TestSelenium:
def setup(self):
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(5)
self.driver.maximize_window() #最大化窗口
def teardown(self):
self.driver.close()
def test_drag_drop(self):
self.driver.get("http://sahitest.com/demo/dragDropMooTools.htm")
# 定位元素
drag_ele = self.driver.find_element_by_id("dragger")
drop_ele = self.driver.find_element_by_xpath("/html/body/div[2]")
# 创建action
action = ActionChains(self.driver)
# 给action添加操作方法
action.drag_and_drop(drag_ele,drop_ele) # 拖拽并移动,传入两个参数,第一个为需要退拽的元素,第二个为释放位置的元素
# 执行action
action.perform()
方法二:
from selenium import webdriver
from selenium.webdriver import ActionChains
import pytest
from time import sleep
class TestSelenium:
def setup(self):
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(5)
self.driver.maximize_window() #最大化窗口
def teardown(self):
self.driver.close()
def test_drag_drop(self):
self.driver.get("http://sahitest.com/demo/dragDropMooTools.htm")
# 定位元素
drag_ele = self.driver.find_element_by_id("dragger")
drop_ele = self.driver.find_element_by_xpath("/html/body/div[2]")
# 创建action
action = ActionChains(self.driver)
# 给action添加操作方法
action.click_and_hold(drag_ele) # 按下不放手
action.release(drop_ele) # 释放鼠标
# 执行action
action.perform()
(4).模拟键盘操作
from selenium import webdriver
from selenium.webdriver import ActionChains
import pytest
from time import sleep
from selenium.webdriver.common.keys import Keys
class TestSelenium:
def setup(self):
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(5)
self.driver.maximize_window() #最大化窗口
def teardown(self):
self.driver.close()
def test_keys(self):
self.driver.get("http://sahitest.com/demo/label.htm")
# 定位元素
ele1 = self.driver.find_element_by_xpath("/html/body/label[1]/input")
ele2 = self.driver.find_element_by_xpath("/html/body/label[2]/table/tbody/tr/td[2]/input")
# 创建action
action = ActionChains(self.driver)
# 给action添加操作方法
ele1.click()
action.send_keys("ouyi1") # 输入内容
action.send_keys(Keys.SPACE) #输入空格
action.send_keys("ouyi2") # 输入内容
action.send_keys(Keys.CONTROL,'a') #全选
action.send_keys(Keys.CONTROL, 'c') # 复制
ele2.click()
action.send_keys(Keys.CONTROL, 'v') # 粘贴
# 执行action
action.perform()
10.3 TouchActions
注意:在web端使用TouchActions时,需要修改谷歌浏览器的启动options
(1)实现滑动
方式一:scroll_from_element----从某个元素开始滑动
from selenium import webdriver
from selenium.webdriver import ActionChains,TouchActions
import pytest
from time import sleep
from selenium.webdriver.common.keys import Keys
class TestSelenium:
def setup(self):
# 设置谷歌的启动配置options
option = webdriver.ChromeOptions()
option.add_experimental_option('w3c',False) #设置谷歌启动方式不要为w3c
self.driver = webdriver.Chrome(options=option)
self.driver.implicitly_wait(5)
self.driver.maximize_window() #最大化窗口
def teardown(self):
self.driver.quit()
def test_touch1(self):
self.driver.get("https://www.taobao.com/")
# 定位元素
ele = self.driver.find_element_by_id("J_TSearchForm")
# 创建action
action = TouchActions(self.driver)
# 给action添加操作方法
"""从某个元素开始滑动。传入三个参数,第一个为开始作为滑动起点的元素,第一个为X偏移量,第三个为y偏移量"""
action.scroll_from_element(ele,0,10000)
# 执行action
action.perform()
方式二:action.scroll(x偏移量,y偏移量)------从当前位置滑动指定的偏移量
action.scroll(0,1000)
11.多窗口的处理
11.1多窗口的识别
(1)获取当前窗口的句柄
driver.current_window_handle #返回当前的窗口句柄
(2)获取所有窗口的句柄
self.driver.window_handles # 返回一个包含所有窗口句柄的列表
11.2多窗口的切换
self.driver.switch_to_window(对应的窗口句柄) #切换到对应的窗口
12.frame处理
12.1 frame简介
12.2 frame的切换
13.selenium多浏览器的处理
我们可以将浏览器作为一个参数,传递给参数用例。来做浏览器的兼容性处理
from selenium import webdriver
from selenium.webdriver import ActionChains,TouchActions
import pytest
from time import sleep
from selenium.webdriver.common.keys import Keys
import os
class TestBroswer:
def setup(self):
# 获取执行测试用例时传入的broswer的值,来判断使用哪个浏览器
broswer = os.getenv('broswer')
if broswer == 'firefox':
self.driver = webdriver.Firefox()
elif broswer == 'chrome':
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(5)
self.driver.maximize_window() # 最大化窗口
def teardown(self):
self.driver.quit()
def test_broswer(self):
self.driver.get("https://www.baidu.com/")
self.driver.find_element_by_id('kw').send_keys('selenium')
self.driver.find_element_by_id('su').click()
这样我们在执行测试用例时,只需要传入broswer对应的值,就可以使用对应的浏览器了。
broswer=chrome pytest -v test_selenium.py
14.selenium执行javascript
在自动化测试中,经常会有一些组件无法定位到。这时需要使用js来进行定位操作。因此我们可以所以selenium中提供的接口来执行JavaScript命令。
14.1 selenium执行JavaScript命令
方式一:执行js命令:driver.execute_script(‘js命令’)
from selenium import webdriver
from time import sleep
class TestJs:
def setup(self):
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(5)
self.driver.maximize_window()
def teardown(self):
self.driver.quit()
def test_js(self):
self.driver.get("https://www.baidu.com/")
# 使用selenium执行js脚本
self.driver.execute_script('alert("selenium")')
sleep(3)
方式二:执行js命令,并将结果返回给selenium代码:driver.execute_script(‘return js命令’)
from selenium import webdriver
from time import sleep
class TestJs:
def setup以上是关于python自动化web自动化:2.web自动化工具selenium讲解的主要内容,如果未能解决你的问题,请参考以下文章