自动化只要掌握四步操作:获取元素,操作元素,获取返回结果,断言(返回结果与期望结果是否一致),最后自动出测试报告,元素定位在这四个环节中是至关重要的,如果说按学习精力分配的话,元素定位占70%;操作元素10%,获取返回结果10%;断言10%。如果一个页面上的元素不能被定位到,那后面的操作就无法继续了。而WebDriver 属于Selenium体系设计出来操作浏览器的一套API,它支持多种语言,Selenium WebDriver只是python的一个第三方框架,也就是说是一个实现web自动化的第三方框架。
一、从如何定位元素开始
1、元素定位:find_element_by_id()
from selenium import webdriver d = webdriver.Chrome() d.get('http://www.baidu.com') d.maximize_window() """ <input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off"> """ # 通过id定位百度搜索框并输入python d.find_element_by_id('kw').send_keys('python')
2、元素定位:find_element_by_name()
说明:如果这里运行后报错,说明这个搜索框的name属性不是唯一的,无法通过name属性直接定位到输入框
from selenium import webdriver d = webdriver.Chrome() d.get('http://www.baidu.com') d.maximize_window() """ <input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off"> """ # 通过name定位百度搜索框并输入python d.find_element_by_name('wd').send_keys('python')
3、元素定位:find_element_by_class_name()
from selenium import webdriver d = webdriver.Chrome() d.get('http://www.baidu.com') d.maximize_window() """ <input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off"> """ # 通过class_name定位百度搜索框并输入python d.find_element_by_class_name('s_ipt').send_keys('python')
4、元素定位:find_element_by_tag_name()
1.从上面定位到的元素属性中,可以看到每个元素都有tag(标签)属性,如搜索框的标签属性,就是最前面的input
2.很明显,在一个页面中,相同的标签有很多,所以一般不用标签来定位。仅供参考和理解,运行肯定报错
from selenium import webdriver d = webdriver.Chrome() d.get('http://www.baidu.com') d.maximize_window() """ <input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off"> """ # 通过tag_name定位百度搜索框并输入python d.find_element_by_tag_name('input').send_keys('python')
5、元素定位:find_element_by_link_text()
from selenium import webdriver d = webdriver.Chrome() d.get('http://www.baidu.com') d.maximize_window() """ <input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off"> """ # 通过link_text定位百度搜索框并输入python d.find_element_by_link_text('登录').click()
6、元素定位:find_element_by_partial_link_text()
1.有时候一个超链接它的字符串可能比较长,如果输入全称的话,会显示很长,这时候可以用一模糊匹配方式,截取其中一部分字符串就可以了
2.如“hao123”,只需输入“ao123”也可以定位到
from selenium import webdriver d = webdriver.Chrome() d.get('http://www.baidu.com') d.maximize_window() """ <input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off"> """ # 通过partial_link_text定位百度搜索框并输入python d.find_element_by_partial_link_text('ao123').click()
7、元素定位:find_element_by_xpath()
以上定位方式都是通过元素的某个属性来定位的,如果一个元素它既没有id、name、class属性也不是超链接,这么办呢?或者说它的属性很多重复的。这个时候就可以用 xpath解决
from selenium import webdriver d = webdriver.Chrome() d.get('http://www.baidu.com') d.maximize_window() """ <input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off"> """ d.find_element_by_xpath('//*[@id="kw"]').send_keys('selenium')
8、元素定位:find_element_by_css_selector()
总结:
selenium的webdriver提供了八种基本的元素定位方法,前面六种是通过元素的属性来直接定位的,后面的xpath和css定位更加灵活,需要重点掌握其中一个。
二、WebDriver API
1、控制浏览器的简单方法
---恢复内容结束---
自动化只要掌握四步操作:获取元素,操作元素,获取返回结果,断言(返回结果与期望结果是否一致),最后自动出测试报告,元素定位在这四个环节中是至关重要的,如果说按学习精力分配的话,元素定位占70%;操作元素10%,获取返回结果10%;断言10%。如果一个页面上的元素不能被定位到,那后面的操作就无法继续了。而WebDriver 属于Selenium体系设计出来操作浏览器的一套API,它支持多种语言,Selenium WebDriver只是python的一个第三方框架,也就是说是一个实现web自动化的第三方框架。
一、从如何定位元素开始
1、元素定位:find_element_by_id()
from selenium import webdriver d = webdriver.Chrome() d.get('http://www.baidu.com') d.maximize_window() """ <input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off"> """ # 通过id定位百度搜索框并输入python d.find_element_by_id('kw').send_keys('python')
2、元素定位:find_element_by_name()
说明:如果这里运行后报错,说明这个搜索框的name属性不是唯一的,无法通过name属性直接定位到输入框
from selenium import webdriver d = webdriver.Chrome() d.get('http://www.baidu.com') d.maximize_window() """ <input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off"> """ # 通过name定位百度搜索框并输入python d.find_element_by_name('wd').send_keys('python')
3、元素定位:find_element_by_class_name()
from selenium import webdriver d = webdriver.Chrome() d.get('http://www.baidu.com') d.maximize_window() """ <input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off"> """ # 通过class_name定位百度搜索框并输入python d.find_element_by_class_name('s_ipt').send_keys('python')
4、元素定位:find_element_by_tag_name()
1.从上面定位到的元素属性中,可以看到每个元素都有tag(标签)属性,如搜索框的标签属性,就是最前面的input
2.很明显,在一个页面中,相同的标签有很多,所以一般不用标签来定位。仅供参考和理解,运行肯定报错
from selenium import webdriver d = webdriver.Chrome() d.get('http://www.baidu.com') d.maximize_window() """ <input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off"> """ # 通过tag_name定位百度搜索框并输入python d.find_element_by_tag_name('input').send_keys('python')
5、元素定位:find_element_by_link_text()
from selenium import webdriver d = webdriver.Chrome() d.get('http://www.baidu.com') d.maximize_window() """ <input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off"> """ # 通过link_text定位百度搜索框并输入python d.find_element_by_link_text('登录').click()
6、元素定位:find_element_by_partial_link_text()
1.有时候一个超链接它的字符串可能比较长,如果输入全称的话,会显示很长,这时候可以用一模糊匹配方式,截取其中一部分字符串就可以了
2.如“hao123”,只需输入“ao123”也可以定位到
from selenium import webdriver d = webdriver.Chrome() d.get('http://www.baidu.com') d.maximize_window() """ <input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off"> """ # 通过partial_link_text定位百度搜索框并输入python d.find_element_by_partial_link_text('ao123').click()
7、元素定位:find_element_by_xpath()
以上定位方式都是通过元素的某个属性来定位的,如果一个元素它既没有id、name、class属性也不是超链接,这么办呢?或者说它的属性很多重复的。这个时候就可以用 xpath解决
from selenium import webdriver d = webdriver.Chrome() d.get('http://www.baidu.com') d.maximize_window() """ <input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off"> """ d.find_element_by_xpath('//*[@id="kw"]').send_keys('selenium')
8、元素定位:find_element_by_css_selector()
总结:
selenium的webdriver提供了八种基本的元素定位方法,前面六种是通过元素的属性来直接定位的,后面的xpath和css定位更加灵活,需要重点掌握其中一个。
二、WebDriver API
1、鼠标常用方法
from selenium import webdriver from selenium.webdriver.common.action_chains import ActionChains d = webdriver.Chrome() d.get('http://www.baidu.com') el = d.find_element_by_link_text('设置') """ ACtionChains()提供的方法: perform() 执行所有的ActionChains中存储的行为 context_click() 右击 double_click() 双击 drag_and_drop(el,el2) 拖动,从el拖动到el2 move_to_element() 鼠标悬停 """ # el.click() # 鼠标悬停ActionChains(d).move_to_element(el).perform()
2、键盘常用属性方法
from selenium import webdriver from selenium.webdriver.common.keys import Keys import time """ 键盘操作被封装到类keys中 """ d = webdriver.Chrome() d.get('http://www.baidu.com') d.find_element_by_id('kw').send_keys('selenuimm') time.sleep(2) # 删除多输入的一个m d.find_element_by_id('kw').send_keys(Keys.BACK_SPACE) time.sleep(2) # 输入空格键+python d.find_element_by_id('kw').send_keys(Keys.BACK_SPACE) d.find_element_by_id('kw').send_keys('python') time.sleep(2) # ctrl+a 全选输入框内容 d.find_element_by_id('kw').send_keys(Keys.CONTROL,'a') time.sleep(2) # ctrl+x 剪切输入框内容 d.find_element_by_id('kw').send_keys(Keys.CONTROL,'x') time.sleep(2) # ctrl+v 粘贴输入框内容 d.find_element_by_id('kw').send_keys(Keys.CONTROL,'v') time.sleep(2) # ctrl+v 粘贴输入框内容 d.find_element_by_id('su').send_keys(Keys.ENTER) time.sleep(2)
3、webelement基本方法
from selenium import webdriver """ size 返回元素的尺寸 text 获取元素的文本 get_attribute(name) 获得属性值 is_displayed() 设置该元素是否是用户可见 """ # 获得输入框的尺寸 size = d.find_element_by_id('kw').size print("size:",size) # 返回百度页面底部备案信息 text = d.find_element_by_id('cp').text print("text:",text) # 返回元素的属性值,可以是id、name、type、或其他属性 attr = d.find_element_by_id('kw').get_attribute('type') print('attr:',attr) # 返回元素的结果是否可见,返回结果为True或者False res = d.find_element_by_id('kw').is_displayed() print("res:",res)
4、获取验证信息
from selenium import webdriver import time d = webdriver.Chrome() d.get('http://www.baidu.com') """ 写自动化测试用例的时候,用来做断言(验证) 三类验证信息 url title text """ # 搜索之前 title = d.title print("title:",title) url = d.current_url print('url:',url) d.find_element_by_id('kw').send_keys('selenium') d.find_element_by_id('su').click() time.sleep(2) # 搜索之后 title = d.title print("title:",title) url = d.current_url print('url:',url) # 断言 if title == 'selenium_百度搜索': print('test case pass') else: print('test case error')
5、设置元素等待
1.显示等待
import time from selenium.webdriver.common.by import By # 元素定位 from selenium.webdriver.support.ui import WebDriverWait # 等待 from selenium.webdriver.support import expected_conditions as EC # 条件判断 from selenium import webdriver """ 显式等待:针对某个元素等待 隐式等待:针对当前页面中的所有元素等待 """ # 方式一 d = webdriver.Chrome() d.get('http://www.baidu.com') # 5是5秒钟,0.5是检测的频率 ele = WebDriverWait(d, 5, 0.5).until( EC.presence_of_element_located((By.ID,'kw')) ) ele.send_keys('selenium') d.quit()
from selenium import webdriver """ 显式等待:针对某个元素等待 隐式等待:针对当前页面中的所有元素等待 """ # 方式二 d = webdriver.Chrome() d.get('http://www.baidu.com') print(time.ctime()) for i in range(10): try: global el el = d.find_element_by_id('kw') if el.is_displayed(): break except: pass time.sleep(1) else: print('time out') el.send_keys('python') # d.close() print(time.ctime())
2.隐式等待
from selenium.webdriver.support.ui import WebDriverWait # 等待 from selenium import webdriver # 隐式等待 d = webdriver.Chrome() # 默认10秒的等待 d.implicitly_wait(10) d.get('http://www.baidu.com') input_ = d.find_element_by_id('kw') input_.send_keys('selenium')
6、定位一组元素
from selenium import webdriver d = webdriver.Chrome() d.get('http://www.baidu.com') """ 定位一组元素:在之前8中定位之前element加s d.find_elements_by_class_name() d.find_elements_by_name() d.find_elements_by_id() d.find_elements_by_link_text() d.find_elements_by_xpath() d.find_elements_by_tag_name() d.find_elements_by_css_selector() d.find_elements_by_partial_link_text() """
7、多表单切换
在web 应用中经常会出现frame 嵌套的应用,假设页面上有A、B 两个frame,其中B 在A 内,那么定位B 中的内容则需要先到A,然后再到B。
switch_to_frame 方法可以把当前定位的主体切换了frame 里。怎么理解这句话呢?我们可以从frame
的实质去理解。frame 中实际上是嵌入了另一个页面,而webdriver 每次只能在一个页面识别,因此才需要
用switch_to.frame 方法去获取frame 中嵌入的页面,对那个页面里的元素进行定位。
switch_to_frame 的参数问题。官方说name 是可以的,但是经过实验发现id 也可以。所以只要frame
中id 和name,那么处理起来是比较容易的。如果frame 没有这两个属性的话,你可以直接手动添加。
注:switch_to_frame() 方法在使用的时候被横线划掉,说明不建议使用
selenium 提供了 switch_to.frame() 方法来切 frame / iframe
以163邮箱登录为例:
from selenium import webdriver import time d = webdriver.Chrome() d.get('https://mail.163.com/') d.implicitly_wait(10) ele = d.find_element_by_id("x-URS-iframe") # 先定位到这个iframe页面 d.switch_to.frame(ele) # 然后切换到这个iframe页面 d.find_element_by_name('email').clear() d.find_element_by_name('email').send_keys('xxxxxx') d.find_element_by_name('password').clear() d.find_element_by_name('password').send_keys('xxxxxxx') d.find_element_by_id('dologin').click() time.sleep(3) d.close()
8、多窗口的切换
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from selenium import webdriver d = webdriver.Chrome() d.implicitly_wait(10) d.get('http://www.baidu.com') # 获得百度搜索窗口句柄 search_window = d.current_window_handle print(search_window) d.find_element_by_link_text('登录').click() d.find_element_by_class_name('tang-pass-footerBar') d.find_element_by_link_text('立即注册').click() # 获得当前所有打开的窗口句柄 all_handles = d.window_handles # 进入注册窗口 for handle in all_handles: if handle != search_window: d.switch_to.window(handle) c_handle = d.current_window_handle # 当前页句柄 print('now register window!') d.find_element_by_id('TANGRAM__PSP_3__userName').send_keys('xxxxxx') d.find_element_by_id('TANGRAM__PSP_3__phone').send_keys('1233323423')
9、警告窗处理
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from selenium import webdriver from selenium.webdriver.common.action_chains import ActionChains import time """ text:返回 alert/confirm/prompt中的文字信息 accept():接受现有警告框 dismiss():解散现有警告框 send_keys(KeysToSend):发送文本至警告框 KeysToSend:将文本发送至警告框 """ driver = webdriver.Chrome() driver.implicitly_wait(10) driver.get("http://www.baidu.com") # 鼠标悬停到设置 obj = driver.find_element_by_link_text("设置") ActionChains(driver).move_to_element(obj).perform() # 点击搜索设置 driver.find_element_by_link_text("搜索设置").click() # 点击保存设置 driver.find_element_by_class_name("prefpanelgo").click() time.sleep(3) # 接受警告框 res = driver.switch_to.alert().text print(res)
10、上传文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from selenium import webdriver driver = webdriver.Chrome() driver.get('http://sahitest.com/demo/php/fileUpload.htm') upload = driver.find_element_by_id('file') upload.send_keys('d:\baidu.py') # send_keys print(upload.get_attribute('value') ) # check value driver.quit()
11、控制浏览器滚动条
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from selenium import webdriver import time #访问百度 driver=webdriver.Chrome() driver.get("http://www.baidu.com") #搜索 driver.find_element_by_id("kw").send_keys("selenium") driver.find_element_by_id("su").click() time.sleep(3) #将页面滚动条拖到底部 js="var q=document.documentElement.scrollTop=10000" driver.execute_script(js) time.sleep(3) #将滚动条移动到页面的顶部 js_="var q=document.documentElement.scrollTop=0" driver.execute_script(js_) time.sleep(3) driver.quit()
12、验证码
对于web 应用来说,大部分的系统在用户登录时都要求用户输入验证码,验证码的类型的很多,有字
母数字的,有汉字的,甚至还要用户输入一条算术题的答案的,对于系统来说使用验证码可以有效果的防
止采用机器猜测方法对口令的刺探,在一定程度上增加了安全性。但对于测试人员来说,不管是进行性能
测试还是自动化测试都是一个棘手的问题
去掉验证码
这是最简单的方法,对于开发人员来说,只是把验证码的相关代码注释掉即可,如果是在测试环境,
这样做可省去了测试人员不少麻烦,如果自动化脚本是要在正式环境跑,这样就给系统带来了一定的风险。
设置万能码
去掉验证码的主要是安全问题,为了应对在线系统的安全性威胁,可以在修改程序时不取消验证码,
而是程序中留一个“后门”---设置一个“万能验证码”,只要用户输入这个“万能验证码”,程序就认为验
证通过,否则按照原先的验证方式进行验证。
验证码识别技术
例如可以通过Python-tesseract 来识别图片验证码,Python-tesseract 是光学字符识别Tesseract OCR 引
擎的Python 封装类。能够读取任何常规的图片文件(JPG, GIF ,PNG , TIFF 等)。不过,目前市面上的验证码
形式繁多,目前任何一种验证码识别技术,识别率都不是100% 。
记录cookie
通过向浏览器中添加cookie 可以绕过登录的验证码,这是比较有意思的一种解决方案。我们可以在
用户登录之前,通过add_cookie()方法将用户名密码写入浏览器cookie ,再次访问系统登录链接将自
动登录
使用cookie 进行登录最大的难点是如何获得用户名密码的name ,如果找到不到name 的名字,就没
办法向value 中输用户名、密码信息。
13、webdriver 原理
1. WebDriver 启动目标浏览器,并绑定到指定端口。该启动的浏览器实例,做为web driver 的remote
server。
2. Client 端通过CommandExcuter 发送HTTPRequest 给remote server 的侦听端口(通信协议: the
webriver wire protocol)
3. Remote server 需要依赖原生的浏览器组件(如:IEDriverServer.exe、chromedriver.exe),来转
化转化浏览器的native 调用。