Selenium是浏览器自动化工具,主要用来Web的自动化测试,以及基于Web的任务管理自动化。它支持的语言有:python、Java、ruby、JavaScript等,而且几乎能在主流的浏览器上运行。css
Selenium2.0、Selenium3.0主要由三大部分组成:SeleniumIDE、Selenium WebDriver、Selenoium Grid。html
VS Selenium RC(Selenium1.0):在浏览器中运行javaScript,使用浏览器内置的JavaScript来翻译和执行selensejava
Web Driver原理python
webDriver是按照client/server模式设计的。client是咱们的测试脚本,发送请求;server就是打开的浏览器,用来接收client的请求并做出响应。web
具体的工做流程:ajax
以web Driver用到的协议:设计模式
其中:浏览器
1)RC原理安全
在Selenium1.0中,是经过Selenium RC服务器做为代理服务器去访问应用从而达到测试的目的。ruby
Selenium RC分为三个部分,Launcher、HttpProxy、Core。
然而直接运行JavaScript会有极大的安全漏洞,因此会受到“同源限制”,在这个基础上,Selenium2.0引入了WebDriver。
2)Web Driver原理
webDriver是按照client/server模式设计的。client是咱们的测试脚本,发送请求;server就是打开的浏览器,用来接收client的请求并做出响应。
具体的工做流程:
因此web Driver用到的协议:
其中:
1)优化测试用例。
2)使用Selenium grid,经过testNG实现并发执行。
说到这里,在编写测试用例的时候,必定要实现松耦合,而后再服务器容许的状况下,尽可能设置多线程实现并发运行。
3)设置等待时间、中断页面加载。若是页面加载内容太多,咱们能够查看一下加载缓慢的缘由,在不影响测试的状况下,能够设置超时时间,中断页面加载。
1. 误报问题。咱们一旦测试用例没有经过,则没法完成每日自动构建,可是其实这些测试用例是正确,也不存在BUG。
2. 主要的缘由:页面尚未加载完成,咱们就开始进行元素定位。
3. 解决方法:重试机制。利用递归封装了一个等待元素的方法。其中,设置最大等待时间为1s,轮询时间为50ms,这个方法会不断轮询,直到方法执行成功或者超过设置的最大等待时间。在咱们最好的一次实践中,咱们把一个测试用例的误报率从10%下降到0,而且执行时间从原先的45秒下降到33秒。
1. 使用四层结构实现业务逻辑、脚本、数据分离。
2. 使用PO设计模式,将一个页面用到的元素和操做步骤封装在一个页面类中。若是一个元素定位发生了改变,咱们只用修改这个页面的元素属性
3. 对于页面类的方法,咱们尽可能从客户的正向逻辑去分析,方法中是一个独立场景,例如:登陆到退出,并且不要想着把全部的步骤都封装在一个方法中。
4. 测试用例设计中,减小测试用例之间的耦合度。
1. 一旦项目发生变化,测试用例就须要改进,工做量大。
2. 验证的范围有限,操做更加复杂,好比说简单的一个验证验证码,若是是人工识别很快就能够输入,可是自动化测试中会增添不少困难。那么这个时候速度也不如人工。
3. 不稳定
4. 可靠性不强
5. 成本与收益
1)区分:display= none VS hidden
共同点:都把网页中的元素给隐藏起来了;在selenium中没法直接定位
区别:none:不为隐藏的对象保留其物理空间 看不见/摸不着
hidden:仍占有空间 看不见/摸得着
页面主要经过"dislay:none"来控制整个下拉框不见。若是直接操做:
from selenium.webdriver.support.ui import WebDriverWait from selenium import webdriver from selenium.webdriver.support.select import Select import os driver = webdriver.Firefox(executable_path="/Users/lesley/Downloads/geckodriver") file_path = 'file:///' + os.path.abspath('test.html') driver.get(file_path) select = driver.find_elements('select') Select(select).select_by_value('volvo') WebDriverWait() driver.quit()
报错:ElementNotVisible
咱们能够通过JavaScript来修改display的值
js = 'document.querySelectortAll('select')[0]'.style.display='block';' select = driver.find_element_by_tag_name('select') Select(select).select_by_value('Opel')
document.querySelectAll('select'):选择全部的select;[0]表示第几个
style.display='block':修改display=block,表示可见
首先,判断一个元素是否显示:is_displayed()
frame是指:页面中嵌入另外一个页面,而webdriver每次只能在一个页面识别,所以须要先定位到相应的frame,对那个页面里的元素进行定位。
此时,有两种方式:
1. iframe存在id 或者name。
首先用switch_to_frame('x-URS-iframe')定位到这个iframe,而后再定位这个iframe中的元素
driver=webdriver.Firefox() driver.get(r'http://www.126.com/') driver.switch_to_frame('x-URS-iframe') #需先跳转到iframe框架 username=driver.find_element_by_name('email') username.clear()
2. iframe不存在name/id。
先定位到iframe,再swith_to_frame
#先定位到iframe elementIframe= driver.find_element_by_class_name('APP-editor-iframe') #再将定位对象传给switch_to_frame()方法 driver.switch_to_frame(elementIframe)
若是完成操做后,能够经过switch_to_parent_content()方法跳出当前iframe,或者还能够经过switch_to_default_content()方法跳回最外层的页面。
获取页面加载状态:
document.readyState
例如:当Selenium点击一个按钮打开一个弹窗,弹窗尚未打开的时候,咱们就要使用弹窗上一个按钮。
——>解决:设置等待最大等待时间
1)sleep():设置固定休眠时间
2)implicity_wait():是webDriver提供的一个超时等待,隐的等待一个元素被发现,或者一个命令完成
3)WebDriverWait():一样也是WebDriver提供的方法。在设置时间内,默认每隔一段时间检测一次当前页面元素是否存在,若是超出指定时间检测不到则抛出异常。
WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None) # driver:WebDriver的驱动程序 # timeout:最长超时时间,默认以秒为单位 # poll_frequency:休眠时间的间隔时间 # ignore_exception():超时后的异常信息,默认状况下抛出NoSuchElementException
一般与until()或者until_not()方法配合使用
until(method, message="") # 调用该方法提供的驱动程序做为一个参数,直到返回值不为FALSE until_not(method, message="") # 调用该方法提供的驱动程序做为一个参数,直到返回值为FALSE
举例:
1 from selenium.webdriver.support.ui import WebDriverWait 2 3 from selenium import webdriver 4 import time 5 6 driver = webdriver.Firefox(executable_path="/Users/lesley/Downloads/geckodriver") 7 driver.get("https://www.baidu.com/") 8 9 # 添加WebDriverWait 10 element = WebDriverWait(driver, 10).until(lambda driver:driver.find_element_by_id("kw")) 11 is_disappeared = WebDriverWait(driver, 5).until_not(lambda x: x.find_element_by_id("someId").is_displayed()) 12 element.send_keys("sbw") 13 14 # 添加智能等待 15 driver.implicitly_wait(5) 16 driver.find_element_by_id("su").click() 17 18 # 添加固定时间等待 19 time.sleep(5) 20 21 driver.quit()
4)WaitFor:配合setTimeout,设置最大等待时间,而后轮询查看是否在指定时间内找到该元素。
1 def waitfor(getter, timeout=3, interval=0.5, *args): 2 starttime = datetime.datetime.now() 3 while True: 4 if getter(args): 5 return 6 else: 7 runtime = datetime.datetime.now() - starttime 8 print runtime 9 if runtime.seconds >= timeout: 10 raise Exception 11 time.sleep(interval) 12 13 current_value = 1 14 def testgetval(args): 15 wanted_value = args[0] 16 global current_value 17 current_value += 1 18 print '%d, %d' % (wanted_value, current_value) 19 return current_value > wanted_value 20 21 if __name__ == '__main__': 22 waitfor(testgetval, 1, 0.3, 2) 23 print '=======================' 24 waitfor(testgetval, 1, 0.3, 8)
如何判断是动态ID?
简单,通常看到元素属性里有拼接一串数字的,就颇有多是动态的。想要分辨,刷新一下浏览器再看该元素,属性值中的数字串改变了,便是动态属性了。
<div id="btn-attention_2030295">...</div>
方式(一)根据相对路径
http://blog.csdn.net/huilan_same/article/details/52541680
方式(二)根据部分元素属性定位
driver.find_element_by_xpath("//div[contains(@id, 'btn-attention')]") driver.find_element_by_xpath("//div[starts-with(@id, 'btn-attention')]") driver.find_element_by_xpath("//div[ends-with(@id, 'btn-attention')]") # 这个须要结尾是‘btn-attention’
——层级定位
# 点击打开菜单栏 driver.find_element_by_xpath("//*[@id='sidebar-collapse']/i").click(); # 点击菜单块 driver.find_element_by_xpath("//*[@id='sidebar']/div[1]/ul/li[2]/a").click(); # 点击“待办中心” driver.find_element_by_linkText("待办案件").click();
driver.find_element_by_xpath("//span[contains(@id, 'sbw')] and not(contains[@style, 'display:none'])")
find_element_by_xpath("//标签名[@属性='属性值']")
例如:
# id属性: driver.find_element_by_xpath("//input[@id='kw']") # class属性: driver.find_element_by_xpath("//input[@class='s_ipt']") # name属性: driver.find_element_by_xpath("//input[@name='wd']") # maxlength属性: driver.find_element_by_xpath("//input[@maxlength='255']")
driver.find_elment_by_xpath('//input')
3)父子定位元素
查找有父亲元素的标签名为span,它的全部标签名叫input的子元素
driver.find_element_by_xpath("//span/input")
例如:
<p id="jgwab"> <i class="c-icon-jgwablogo"></i> 京公网安备11000002000001号 </p>
则咱们能够定位:
# 根据text()
driver.find_elment_by_xpath('//p[contains(text(), '京公网')]')
# 根据class
driver.find_elment_By_xpath('//p[contains(@class, '京公网')]')
//父元素标签名/标签名的属性值:指的是span下的input标签下class属性为s_ipt的元素
driver.find_element_by_xpath("//span/input[@class='s_ipt']")
指的是input标签下id属性为kw且name属性为wd的元素
driver.find_element_by_xpath("//input[@class='s_ipt' and @name='wd']")
指的是p标签下内容包含“京公网”且id属性为jgwab的元素
find_element_by_xpath("//p[contains(text(),'京公网') and @id='jgwab']")
element.click()
element.send_keys('test')
element.send_keys('D\test.txt')
#双击 ActionChains(driver).double_click(element).perform() #右击 ActionChains(driver).context_click(element).perform() #拖动 ActionChains(driver).drag_and_drop(element).perform() #悬停 ActionChains(driver).move_to_element(element).perform()
from selenium.webdriver.support.ui import Select Select(driver.find_element_by_id('gender')).select_by_value('2') Select(driver.find_element_by_id('gender')).select_by_index(1) Select(driver.find_element_by_id('gender')).select_by_visible_text('Male')
Dropdown1 = driver.find_element_by_id(‘id’) #先定位到dropdown Dropdown1.find_element_by_id(“li2_input_2”) #再定位到dropdown中的值
3)使用js实现:
driver.switch_to_alert().accept() # 接收弹窗 driver.switch_to_alert().dismiss() # 取消弹窗 # 获取弹窗的文本消息 Message = driver.switch_to_alert().text
driver.refresh() # 刷新 driver.back() # 后退 driver.forward() # 前进 driver.maximize_window() # 最大化 driver.set_window_size(100,200) # 设置窗口大小 driver.switch_to.window(searchwindow)
driver.switch_to.frame(ReferenceFrame) driver.switch_to.parent_frame() # frame须要一级一级切 driver.switch_to.default_content() # 返回最外层
:等到某个条件成立时继续执行。每隔一段时间检测,超出最大时间则抛出异常
is_disappeared = WebDriverWait(driver, 5).until_not(lambda x: x.find_element_by_id("someId").is_displayed())
隐式等待中的时间并不是一个固定的等待时间,它并不影响脚本的执行速度。好比进行某元素的定位时,若是元素能够定位就继续执行,若是目前定位不到就以轮询的方式持续判断该元素是否被定位到,若是超过规定的时间还没定位到就抛出异常。
driver.implicitly_wait(20)
from time import sleep sleep(5)
3. selenium中如何保证操做元素的成功率?也就是说如何保证我点击的元素必定是能够点击的?
Selenium有八种定位方式:
若是存在id,我必定使用Id,由于简单方便,定位最快。其次是Xpath,由于不少状况下html标签的属性不够规范,没法惟必定位。Xpath是经过相对位置定位
首先触发动态事件,而后再定位。若是是动态菜单,则须要层级定位。——JS实现(对动态事件封装)
http://www.cnblogs.com/tobecrazy/p/4817946.html
属性动态变化也就是指该元素没有固定的属性值,能够经过:
http://www.cnblogs.com/zhaozhan/archive/2009/09/10/1564332.html
不会的。因此有的时候,当selenium并未加载完一个页面时再请求页面资源,则会误报不存在此元素。因此首先咱们应该考虑判断,selenium是否加载完此页面。其次再经过函数查找该元素。
1)断言(assert):测试将会在检查失败时中止,并不运行后续的检查
优势:能够直截了当的看到检查是否经过
缺点:检查失败后,后续检查不会执行,没法收集那些检查结果状态
2)验证(vertify):将不会终止测试
缺点:你必须作更多的工做来检查测试结果:查看日志——>耗时多,因此更偏向于断言
# 断言验证:百度搜索的标题是否为:百度搜索 # import unittest try: self.assertEqual(u"百度搜素", driver.title) except AssertionError as e: print("Cannot find this title")
3)Waitfor:用于等待某些条件变为真。可用于AJAX应用程序的测试。
若是该条件为真,他们将当即成功执行。若是该条件不为真,则将失败并暂停测试。直到超过当前所设定的超时时间。 通常跟setTimeout时间一块儿用。
经常使用的断言:
1 assertLocation # 判断当前是在正确的页面 2 assertTitle #检查当前页面的title是否正确 3 assertValue # 检查input的值, checkbox或radio,有值为”on”无为”off” 4 assertSelected # 检查select的下拉菜单中选中是否正确 5 assertSelectedOptions # 检查下拉菜单中的选项的是否正确 6 assertText # 检查指定元素的文本 7 assertTextPresent # 检查在当前给用户显示的页面上是否有出现指定的文本 8 assertTextNotPresent # 检查在当前给用户显示的页面上是否没有出现指定的文本 9 assertAttribute # 检查当前指定元素的属性的值 10 assertTable # 检查table里的某个cell中的值 11 assertEditable # 检查指定的input是否能够编辑 12 assertNotEditable # 检查指定的input是否不能够编辑 13 assertAlert # 检查是否有产生带指定message的alert对话框 14 waitForElementPresent # 等待检验某元素的存在。为真时,则执行。
不可以。Ajax是一种支持动态改变用户界面元素的技术。在Ajax驱动的应用程序中,数据能够从应用服务器检索,而后显示在页面上,而不须要加载整个页面,只有一小部分页面或者元素自己被从新加载。
因此不可以使用ClickAndWait,由于Ajax call不会刷新整个页面,clickAndWait命令会由于等待页面从新加载而出现time out。
也就是说最大的麻烦是判断Ajax调用是否结束。能够用click + pause完成
使用JQuery进行辅助测试:http://www.cnblogs.com/nbkhic/archive/2011/10/23/2221729.html
其中,去哪儿网的题目以下:
1、 UI自动化测试
Qunar机票搜索场景
1) 访问Qunar机票首页http://flight.qunar.com,选择“单程”,输入出发、到达城市,选择today+7往后的日期,点“搜索”,跳转到机票单程搜索列表页。
2) 在列表页停留1分钟,至到页面上出现“搜索结束”。
3) 若是出现航班列表,对于出现“每段航班均需缴纳税费”的行随机点选“订票”按钮,在展开的列表中会出现“第一程”、 “第二程”;
对于没有出现“每段航班均需缴纳税费”的行随机点选“订票”按钮,在展开的列表底部中会出现“报价范围”
4) 若是不出现航班列表,则页面会出现“该航线当前无可售航班”
请使用maven建立java工程,引入Selenium框架,编写WebUI代码,实现上述人工操做和验证。要求能随机验证100个城市对的3个月内的任意搜索条件。
参见答案:http://www.cnblogs.com/tobecrazy/p/4752684.html
不少人可能第一步就卡住了,怎么选择7天之后的日期呢?
实际上很简单,直接在输入框里输入就行了。由于selenium支持的语言不少,这里就用js写一下。你们用selenium执行这段js就能够搞定了。
var date = new Date(); date.setDate(date.getDate() + 7); var a_week_later = date.getFullYear() + '-' (date.getMonth()+1) + '-' + date.getDate(); $('input[name=fromDate]').val(a_week_later);
参考答案: http://www.cnblogs.com/tobecrazy/p/5873288.html