1. 什么是Selenium
Selenium是一个免费的(开源)自动化测试组件,适用于跨不同浏览器和平台的Web应用程序。它非常类似于HP Quick Test Pro (QTP现在叫UFT),只是Selenium侧重于自动化基于Web的应用程序。使用Selenium工具进行的测试通常称为Selenium测试。
Selenium的组成
整个Selenium工具套件由四个组件组成:
Selenium IDE,一个Firefox插件,您只能在创建相对简单的测试用例和测试套件时使用它。
Selenium RC,也称为Selenium 1,它是第一个允许用户使用编程语言创建复杂测试的Selenium工具。
WebDriver是一个新的突破,它允许您的测试脚本直接与浏览器通信,从而从操作系统级别控制它。
Selenium Grid也是一个工具,它与Selenium RC一起用于跨不同的浏览器和操作系统执行并行测试。
Selenium RC与WebDriver合并形成Selenium 2,现已经更新到了Selenium 3 和Selenium 4。
Selenium的优点
Selenium在成本和灵活性方面比QTP更有优势。它还允许您并行地运行测试,而不像在QTP中,您只允许顺序地运行测试。
-
- 成本(因为Selenium是完全免费的)
- 灵活性(因为Selenium可以支持多种编程语言、浏览器和平台)
- 并行测试(这是QTP能够做到的,但只有使用质量中心)
Quick Test Professional(QTP)是一种专有的自动化测试工具,在2006年被惠普收购之前,它曾属于Mercury Interactive公司。
2. Selenium3 浏览器驱动
下载浏览器驱动
下载Driver要注意和你当前已有的浏览器的版本是否一致
Chrome浏览器驱动:chromedriver
IE浏览器驱动:IEDriverServer
Edge浏览器驱动:MicrosoftWebDriver
设置浏览器驱动
我的电脑-->属性-->系统设置-->高级-->环境变量-->系统变量-->Path,将存放浏览器驱动的目录添加到Path的值中。
或者 浏览器驱动放到与python.exe同级目录中
3. selenium元素定位
Selenium提供了8种定位方式。
- id
- name
- class name
- tag name
- link text
- partial link text
- xpath
- css selector
这8种定位方式在Python selenium中所对应的方法为:
- find_element_by_id()
- find_element_by_name()
- find_element_by_class_name()
- find_element_by_tag_name()
- find_element_by_link_text()
- find_element_by_partial_link_text()
- find_element_by_xpath()
- find_element_by_css_selector()
例
#通过id定位: dr.find_element_by_id("kw") #通过name定位: dr.find_element_by_name("wd") #通过class name定位: dr.find_element_by_class_name("s_ipt") #通过tag name定位: dr.find_element_by_tag_name("input") #通过xpath定位,xpath定位有N种写法,这里列几个常用写法: dr.find_element_by_xpath("//*[@id='kw']") dr.find_element_by_xpath("//*[@name='wd']") dr.find_element_by_xpath("//input[@class='s_ipt']") dr.find_element_by_xpath("/html/body/form/span/input") dr.find_element_by_xpath("//span[@class='soutu-btn']/input") dr.find_element_by_xpath("//form[@id='form']/span/input") dr.find_element_by_xpath("//input[@id='kw' and @name='wd']") #通过css定位,css定位有N种写法,这里列几个常用写法: dr.find_element_by_css_selector("#kw") dr.find_element_by_css_selector("[name=wd]") dr.find_element_by_css_selector(".s_ipt") dr.find_element_by_css_selector("html > body > form > span > input") dr.find_element_by_css_selector("span.soutu-btn> input#kw") dr.find_element_by_css_selector("form#form > span > input") # 通过link text定位: dr.find_element_by_link_text("新闻") dr.find_element_by_link_text("hao123") # 通过link text定位: dr.find_element_by_partial_link_text("新") dr.find_element_by_partial_link_text("hao") dr.find_element_by_partial_link_text("123")
3.1 通过Xpath定位
Xpath语法
https://www.w3school.com.cn/xpath/xpath_syntax.asp
一:从根目录/开始
有点像Linux的文件查看,/代表根目录,一级一级的查找,直接子节点,相当于css_selector中的>号
/html/body/div/p
二. 根据元素属性选择:
查找具体的元素,必须在前面输入标准开头//,表示从当前节点寻找所有的后代元素
//div/* div下面的所有的元素
//div//p 先在整个文档里查找div,再在div里查找p节点(只要在内部,不限定是否紧跟) ;等价于 css_selector里的('div p')
//div/p p是div的直接子节点; 等价于 css_selector里的('div > p')
//*[@style] 查找所有包含style的所有元素,所有的属性要加@; 等价于 css_selector里的('*[style]')
//p[@spec='len'] 必须要加引号;等价于 css_selector里的("p[spec='len']")
//p[@id='kw'] xpath中对于id,class与其他元素一视同仁,没有其他的方法
//a[contains(@href,'permalink')] href属性中包含permalink的a
//input[@type='text' and @name='wd'] 多个属性组合(逻辑运算)
//input[starts-with(@class,'s_ip')] 模糊匹配以xx开头:starts-with
//*[text()=‘文本内容’] 对于这种文本属性
三. 选择第几个节点
//div/p[2] 选择div下的第二个p节点 ;等价于css_selector里的div>p:nth-of-type(2) 符合p类型的第二个节点
//div/*[2] 选择div下第二个元素
//div/p[position()=2] position()=2 指定第二个位置; 等价于上面的 //div/p[2]
position()>=2 位置大于等于2
position()<2 位置小于2
position()!=2 位置不等于2
//div/p[last()] 选择div下的倒数第一个p节点; last()倒数第一个
//div/p[last()-1] 选择div下的倒数第二个p节点;
//div/p[position()=last()] 倒数第一个
//div/p[position()=last()-1] 倒数第二个
//div/p[position()>=last()-2] 倒数第一个,第二个,第三个
四. 组合选择
//p | //button 选择所有的p和button,等价于css_selector里的 p, button
//input[@id='kw' and @class='su'] 选择id=kw 并且 class="su"的input元素
五. 兄弟节点的选择
相邻后面的兄弟节点的选择:following-sibling:: 两个冒号
//div/following-sibling::p 选择div里相邻的p节点
相邻前面的兄弟节点的选择:preceding-sibling:: 此方法在css_selector中没有
//div/preceding-sibling::p[2] 选择div里前面相邻的第二个节点,不加[2]选择的是前面的所有的p节点
六. 选择父节点
//p[@spec='len']/.. 选择p节点的上层节点 此方法在css_selector中没有
//p[@spec='len']/../.. 上层节点的上层节点
七. 在webelement对象里面使用查找Xpath 查找时,必须使用.指明当前节点
food = driver.find_element_by_id('food')
eles = food.find_elements_by_xpath(".//p") .指明当前节点
eles = food.find_elements_by_xpath("..") 查找当前节点的父节点
3.2 通过CSS Selector 定位
一:通过ID定位
find_element_by_css_selector("#Email")
find_element_by_css_selector("input#Email")
二:通过Class定位
find_element_by_css_selector(".remember")
find_element_by_css_selector("label.remember")
三: 通过属性定位
find_element_by_css_selector("input")
find_element_by_css_selector("[name='wd']")
find_element_by_css_selector("input[type=’submit’]")
四: 通过位置定位
find_element_by_css_selector("span input")
find_element_by_css_selector("span > input")
find_element_by_css_selector("span + input.s_ipt")
find_element_by_css_selector("ul > li:nth-chlid(2)")
五: 常用CSS Selector
パターン | 意味 |
---|---|
* |
任意的元素 |
E |
Type E 的元素 |
E[foo] |
有"foo" 属性的 E 元素 |
E[foo="bar"] |
"foo" 属性値等于 "bar" 的 E 元素 |
E[foo^="bar"] |
"foo" 属性値 "bar" 开始的 E 元素 |
E[foo$="bar"] |
"foo" 属性値 "bar" 结尾的 E 元素 |
E[foo*="bar"] |
"foo" 属性値含有 "bar" 的 E 元素 |
E:root |
E 元素 (document的根) |
E:nth-child(n) |
E 元素 (親から n 番目の子) |
E:nth-last-child(n) |
E 元素 (最後の元素から数えて、親の n 番目の子元素) |
E:nth-of-type(n) |
E 元素 (同タイプの n 番目の兄弟) |
E:nth-last-of-type(n) |
E 元素 (最後の元素から数えて、そのタイプの n 番目の兄弟元素) |
E:first-child |
E 元素 (親の最初の子) |
E:last-child |
E 元素 (親の最後の子) |
E:first-of-type |
E 元素 (同タイプの最初の兄弟) |
E:last-of-type |
E 元素 (同タイプの最後の兄弟) |
E F |
E 元素の子孫 F 元素 |
E > F |
E 元素の子 F 元素 |
E + F |
E 元素の直後の F 元素 |
E ~ F |
E 元素の後のF 元素 |
4. 控制浏览器操作
设置浏览器的大小
driver.set_window_size(480, 800)
控制浏览器后退、前进
driver.back()
driver.forward()
刷新页面
driver.refresh()
from selenium import webdriver driver = webdriver.Firefox() #访问百度首页 first_url= 'http://www.baidu.com' print("now access %s" %(first_url)) driver.get(first_url) # 参数数字为像素点 print("设置浏览器宽480、高800显示") driver.set_window_size(480, 800) #访问新闻页面 second_url='http://news.baidu.com' print("now access %s" %(second_url)) driver.get(second_url) #返回(后退)到百度首页 print("back to %s "%(first_url)) driver.back() #前进到新闻页 print("forward to %s"%(second_url)) driver.forward() driver.refresh() #刷新当前页面 driver.quit()
5. WebDriver常用方法
点击和输入
clear(): 清除文本。
send_keys (value): 模拟按键输入。
click(): 单击元素。
提交
submit()
其他常用方法
size: 返回元素的尺寸。
text: 获取元素的文本。
get_attribute(name): 获得属性值。
is_displayed(): 设置该元素是否用户可见。
from selenium import webdriver driver = webdriver.Chrome() driver.get("http://www.baidu.com") # 获得输入框的尺寸 size = driver.find_element_by_id('kw').size print(size) # 返回百度页面底部备案信息 text = driver.find_element_by_id("cp").text print(text) # 返回元素的属性值, 可以是 id、 name、 type 或其他任意属性 attribute = driver.find_element_by_id("kw").get_attribute('type') print(attribute) # 返回元素的结果是否可见, 返回结果为 True 或 False result = driver.find_element_by_id("kw").is_displayed() print(result) driver.find_element_by_id("kw").clear() driver.find_element_by_id("kw").send_keys("selenium") driver.find_element_by_id("su").click() search_text.submit() driver.quit()
6. 鼠标事件
perform(): 执行所有 ActionChains 中存储的行为;
context_click(): 右击;
double_click(): 双击;
drag_and_drop(): 拖动;
move_to_element(): 鼠标悬停。
from selenium import webdriver # 引入 ActionChains 类 from selenium.webdriver.common.action_chains import ActionChains driver = webdriver.Chrome() driver.get("https://www.baidu.cn") # 定位到要悬停的元素 above = driver.find_element_by_link_text("设置") # 对定位到的元素执行鼠标悬停操作 ActionChains(driver).move_to_element(above).perform()
7. 键盘事件
在使用键盘按键方法前需要先导入 keys 类。
from selenium.webdriver.common.keys import Keys
from selenium import webdriver # 引入 Keys 模块 from selenium.webdriver.common.keys import Keys driver = webdriver.Chrome() driver.get("http://www.baidu.com") # 输入框输入内容 driver.find_element_by_id("kw").send_keys("seleniumm") # 删除多输入的一个 m driver.find_element_by_id("kw").send_keys(Keys.BACK_SPACE) # 输入空格键+“教程” driver.find_element_by_id("kw").send_keys(Keys.SPACE) driver.find_element_by_id("kw").send_keys("教程") # ctrl+a 全选输入框内容 driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'a') # ctrl+x 剪切输入框内容 driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'x') # ctrl+v 粘贴内容到输入框 driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'v') # 通过回车键来代替单击操作 driver.find_element_by_id("su").send_keys(Keys.ENTER) driver.quit()
以下为常用的键盘操作:
send_keys(Keys.BACK_SPACE) 删除键(BackSpace)
send_keys(Keys.SPACE) 空格键(Space)
send_keys(Keys.TAB) 制表键(Tab)
send_keys(Keys.ESCAPE) 回退键(Esc)
send_keys(Keys.ENTER) 回车键(Enter)
send_keys(Keys.CONTROL,'a') 全选(Ctrl+A)
send_keys(Keys.CONTROL,'c') 复制(Ctrl+C)
send_keys(Keys.CONTROL,'x') 剪切(Ctrl+X)
send_keys(Keys.CONTROL,'v') 粘贴(Ctrl+V)
send_keys(Keys.F1) 键盘 F1
8. 获取信息
不管是在做功能测试还是自动化测试,最后一步需要拿实际结果与预期进行比较。这个比较的称之为断言。
我们通常可以通过获取title 、URL和text等信息进行断言。
title:用于获得当前页面的标题。
current_url:用户获得当前页面的URL。
text:获取搜索条目的文本信息。
# 打印当前页面title title = driver.title print(title) # 打印当前页面URL now_url = driver.current_url print(now_url) # 获取结果数目 user = driver.find_element_by_class_name('nums').text print(user)
9. 设置元素等待
WebDriver提供了两种类型的等待:显式等待和隐式等待。
显式等待
显式等待使WebdDriver等待某个条件成立时继续执行,否则在达到最大时长时抛出超时异常(TimeoutException)。
WebDriverWait类是由WebDirver 提供的等待方法。.
在设置时间内,默认每隔一段时间检测一次当前页面元素是否存在,如果超过设置时间检测不到则抛出异常
WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)
◆ driver :浏览器驱动。
◆ timeout :最长超时时间,默认以秒为单位。
◆ poll_frequency :检测的间隔(步长)时间,默认为0.5S。
◆ ignored_exceptions :超时后的异常信息,默认情况下抛NoSuchElementException异常。
WebDriverWait()一般由until()或until_not()方法配合使用,下面是until()和until_not()方法的说明。
◆ until(method, message=‘’)
调用该方法提供的驱动程序作为一个参数,直到返回值为True。
until_not(method, message=‘’)
调用该方法提供的驱动程序作为一个参数,直到返回值为False。
在本例中,通过as关键字将expected_conditions 重命名为EC,并调用presence_of_element_located()方法判断元素是否存在。
隐式等待
implicitly_wait()
默认参数的单位为秒
from selenium import webdriver from selenium.common.exceptions import NoSuchElementException from time import ctime driver = webdriver.Firefox() # 设置隐式等待为10秒 driver.implicitly_wait(10) driver.get("http://www.baidu.com") try: print(ctime()) driver.find_element_by_id("kw22").send_keys('selenium') except NoSuchElementException as e: print(e) finally: print(ctime()) driver.quit()
本例中设置等待时长为10秒。首先这10秒并非一个固定的等待时间,它并不影响脚本的执行速度。
它并不针对页面上的某一元素进行等待。当脚本执行到某个元素定位时,如果元素可以定位,则继续执行;
如果元素定位不到,则它将以轮询的方式不断地判断元素是否被定位到。
假设在第6秒定位到了元素则继续执行,若直到超出设置时长(10秒)还没有定位到元素,则抛出异常。
10. 定位一组元素
- find_elements_by_id()
- find_elements_by_name()
- find_elements_by_class_name()
- find_elements_by_tag_name()
- find_elements_by_link_text()
- find_elements_by_partial_link_text()
- find_elements_by_xpath()
- find_elements_by_css_selector()
11. 多表单切换
driver.switch_to.frame('frameId')
driver.switch_to.parent_frame()
driver.switch_to.default_content()
driver = webdriver.Chrome() driver.get("http://www.126.com") driver.switch_to.frame('x-URS-iframe') driver.find_element_by_name("email").clear() driver.find_element_by_name("email").send_keys("username")
当ID是随机内容,不可用的时候,直接定位frame(0) 即第一个frame
driver.switch_to.frame(0)
12. 多窗口切换
current_window_handle:获得当前窗口句柄。
window_handles:返回所有窗口的句柄到当前会话。
switch_to.window(handle):用于切换到相应的窗口,用于不同表单之间的切换。
from selenium import webdriver import time driver = webdriver.Firefox() driver.implicitly_wait(10) driver.get("http://www.baidu.com") # 获得百度搜索窗口句柄 sreach_windows = driver.current_window_handle driver.find_element_by_link_text('登录').click() driver.find_element_by_link_text("立即注册").click() # 获得当前所有打开的窗口的句柄 all_handles = driver.window_handles # 进入注册窗口 for handle in all_handles: if handle != sreach_windows: driver.switch_to.window(handle) print('now register window!') driver.find_element_by_name("account").send_keys('username') driver.find_element_by_name('password').send_keys('password') time.sleep(2) # …… driver.quit()
13. 警告框处理
switch_to_alert() : 接受这个弹窗。
text:返回 alert/confirm/prompt 中的文字信息。
accept():接受现有警告框。
dismiss():解散现有警告框。
send_keys(keysToSend):发送文本至警告框。keysToSend:将文本发送至警告框。
# 接受警告框 driver.switch_to.alert.accept()
14. 下拉框选择
from selenium.webdriver.support.select import Select
Select类用于定位select标签。
select_by_value() 方法用于定位下接选项中的value值。
# 搜索结果显示条数 sel = driver.find_element_by_xpath("//select[@id='nr']") Select(sel).select_by_value('50') # 显示50条
15. 文件上传
对于通过input标签实现的上传功能,可以将其看作是一个输入框,即通过send_keys()指定本地文件路径的方式实现文件上传。
# 定位上传按钮,添加本地文件 driver.find_element_by_name("file").send_keys('D:\upload_file.txt')
16. cookie操作
WebDriver操作cookie的方法:
get_cookies(): 获得所有cookie信息。
get_cookie(name): 返回字典的key为“name”的cookie信息。
add_cookie(cookie_dict) : 添加cookie。“cookie_dict”指字典对象,必须有name 和value 值。
delete_cookie(name,optionsString):删除cookie信息。“name”是要删除的cookie的名称,“optionsString”是该cookie的选项,目前支持的选项包括“路径”,“域”。
delete_all_cookies(): 删除所有cookie信息。
from selenium import webdriver driver = webdriver.Firefox() driver.get("http://www.youdao.com") # 向cookie的name 和value中添加会话信息 driver.add_cookie({'name': 'key-aaaaaaa', 'value': 'value-bbbbbb'}) # 遍历cookies中的name 和value信息并打印,当然还有上面添加的信息 for cookie in driver.get_cookies(): print("%s -> %s" % (cookie['name'], cookie['value'])) driver.quit()
17. 调用JavaScript代码
driver.execute_script()
# 通过javascript设置浏览器窗口的滚动条位置 js="window.scrollTo(100,450);" driver.execute_script(js) sleep(3)
这样可以实现滚动到指定元素
element.location_once_scrolled_into_view
18. 调用JavaScript代码窗口截图
# 截取当前窗口,并指定截图图片的保存位置 driver.get_screenshot_as_file("D:\baidu_img.jpg")
19. 关闭浏览器
close() 关闭单个窗口
quit() 关闭所有窗口
————————————————————————————————————————————————————————————————
参考链接:
1. https://blog.csdn.net/u012941152/java/article/details/83011110 作者 雪国的花儿
2. https://blog.csdn.net/zbj18314469395/article/details/99652088 作者 软测小生
3. http://www.testclass.net/selenium_python 主要参考 作者 虫师