最近有python开发的项目,也正打算要学习自动化与python语言。所以想经过学习python版本的webdriver来一同窗习。javascript
学习过程当中参考资料有乙醇的博客:https://github.com/easonhan007/webdriver_guide/blob/master/README.md,虫师的博客:http://www.cnblogs.com/fnng/css
以及python的官方文档:http://docs.seleniumhq.org/docs/03_webdriver.jsp#firefox-driverhtml
selenium webdriver的API介绍java
webdriver的是一个Web应用程序测试自动化工具,用来验证程序是否如预期的那样执行。它的目的是提供一个友好的API,比selenium RC(1.0)API更容易使用,这将有助于使你的测试脚本更容易阅读和维护。它不依赖于任何特定的测试框架,因此它能够用于单元测试或者一个老式的“main”方法中。本节介绍webdriver的API,下面让咱们来帮助你熟悉它。python
若是你已经设置了项目,你就会发现,webdriver的做用跟其它库同样:它是彻底独立的,你一般在使用以前不须要启动任何额外的进程,或者运行任何安装程序,若是使用Selenium-RC则要到代理服务器。 git
注:须要额外的驱动来使脚本在不一样环境下运行:Chrome Driver, Opera Driver, Android Driver andiPhone Driver。默认是支持的Firefox Driver。github
如今咱们经过一个代码来了解其机制。代码实现:打开浏览器,输入谷歌网页,并在搜索框内输入“Cheese” 点击搜索,最后关闭浏览器。web
from selenium import webdriver from selenium.common.exceptions import TimeoutException from selenium.webdriver.support.ui import WebDriverWait # available since 2.4.0 from selenium.webdriver.support import expected_conditions as EC # available since 2.26.0 # Create a new instance of the Firefox driver driver = webdriver.Firefox() # go to the google home page driver.get("http://www.google.com") # find the element that's name attribute is q (the google search box) inputElement = driver.find_element_by_name("q") # type in the search inputElement.send_keys("Cheese!") # submit the form (although google automatically searches now without submitting) inputElement.submit() # the page is ajaxy so the title is originally this: print driver.title try: # we have to wait for the page to refresh, the last thing that seems to be updated is the title WebDriverWait(driver, 10).until(EC.title_contains("cheese!")) # You should see "cheese! - Google Search" print driver.title finally: driver.quit()
在下面的章节中,您将了解更多有关如何使用webdriver的东西,如如何使用浏览器的前进和后退功能(这在selenium 1.0中不能被很好的支持);以及如何使用框架和窗口测试网站。咱们将会提供了更深刻的讨论和范例。 ajax
Selenium webdriver的API命令和操做chrome
取回页面
你可能使用webdriver想要作的第一件事是导航到一个页面,经过“get”能够轻松的作到之一点
driver.get(http://www.google.com)
webdriver的运行依赖于几个因素:包括操做系统/浏览器的组合,有时可能须要等待页面加载。webdriver的在某些状况下,可能须要控制返回页面的开始与加载时间。为了确保脚本的稳定性,须要等待的元素(S)在页面中存在的 显性和隐性的等待。
定位UI元素(WebElements)
参考:http://www.cnblogs.com/fnng/archive/2012/01/12/2321117.html
自动化要想模拟用户(人)的行为操做,首先须要识别并定位UI上的元素,每一个元素都有特定属性,webdriver就是经过识别元素的属性来定位元素。
咱们能够经过下面的一些属性或方法来定定位元素:
ID
这是最有效和最优选的方式来定位一个元素。常见的陷阱,开发人员能够为元素设置非惟一的ID ,或经过自动生成ID ,应该避免这种状况。
如何经过ID的方式定位一个元素,看下面这样的例子:
<div id="coolestWidgetEvah">...</div> element = driver.find_element_by_id("coolestWidgetEvah") or from selenium.webdriver.common.by import By element = driver.find_element(by=By.ID, value="coolestWidgetEvah")
By class name
“class ”是指DOM元素的属性。但在实际使用中有不少相同类名的DOM元素,在发现多个相同类名的元素时,程序会默认选择最早找到的第一个元素。
如何经过类名找到一个元素,看下面的例子:
<div class="cheese"> <span>Cheddar</span> </div> <div class="cheese"> <span>Gouda</span> </div> cheeses = driver.find_elements_by_class_name("cheese") or from selenium.webdriver.common.by import By cheeses = driver.find_elements(By.CLASS_NAME, "cheese")
By tag name
DOM标签名称的元素。
具体方式以下面的例子:
<iframe src="..."></iframe> frame = driver.find_element_by_tag_name("iframe") or from selenium.webdriver.common.by import By frame = driver.find_element(By.TAG_NAME, "iframe") By name
查找并匹配元素的name属性
具体方式以下面的例子:
<input name="cheese" type="text"/> cheese = driver.find_element_by_name("cheese") or from selenium.webdriver.common.by import By cheese = driver.find_element(By.NAME, "cheese") By link text
经过连接文本找到元素匹配
例子以下:
<a href="http://www.google.com/search?q=cheese">cheese</a>> cheese = driver.find_element_by_link_text("cheese") or from selenium.webdriver.common.by import By cheese = driver.find_element(By.LINK_TEXT, "cheese") By Partial Link Text
经过查找部分连接文件匹配元素
例子以下:
<a href="http://www.google.com/search?q=cheese">search for cheese</a>> cheese = driver.find_element_by_partial_link_text("cheese") or from selenium.webdriver.common.by import By cheese = driver.find_element(By.PARTIAL_LINK_TEXT, "cheese")
By CSS
经过CSS的定位策略。默认状况下本机浏览器支持CSS定位,因此,请参考W3C CSS选择器
<http://www.w3.org/TR/CSS/#selectors> 显示通常可用的CSS选择器的列表。若是浏览器没有原生支持CSS查询,可使用Sizzle(Sizzle是一个纯javascript CSS选择器引擎)。目前,IE 6,7和FF3.0使用Sizzle的CSS查询引擎。
注意:不是全部浏览器对CSS的支持都是同样的,可能在一个浏览器中运行良好,切换到另外一个浏览器则否则。
具体用法以下:
<div id="food"> <span class="dairy">milk</span> <span class="dairy aged">cheese</span> </div> cheese = driver.find_element_by_css_selector("#food span.dairy.aged") or from selenium.webdriver.common.by import By cheese = driver.find_element(By.CSS_SELECTOR, "#food span.dairy.aged") By XPATH
在高的级别上,尽量的使用一个浏览器原生的webdriver XPath 的功能。在一些没有本地的XPath支持的浏览器,咱们已经提供了咱们本身的实现。这可能会致使一些意想不到的行为,除非你知道各类XPath引擎的差别。
驱动 |
标签和属性名称 |
属性值 |
本地的XPath支持 |
HtmlUnit Driver |
小写 |
当他们出如今HTML |
是 |
Internet Explorer Driver |
小写 |
当他们出如今HTML |
没有 |
Firefox Driver |
不区分大小写 |
当他们出如今HTML |
是 |
这点抽象,对于下面这段HTML 代码来讲:
<input type="text" name="example" /> <INPUT type="text" name="other" /> inputs = driver.find_elements_by_xpath("//input") or from selenium.webdriver.common.by import By inputs = driver.find_elements(By.XPATH, "//input")
不一样驱动对大小写的支持:
XPath expression |
|||
//input |
1 (“example”) |
2 |
2 |
//INPUT |
0 |
2 |
0 |
HTML元素有时并不须要显式地声明,由于他们默认为已知值的属性。例如,“input”的标签并不须要的“type”属性,由于它默认为“text”。webdriver使用XPath时,你不该该指望可以对这些隐含的属性相匹配。
使用JavaScript
你能够执行任意javascript来找到一个元素,只要你返回一个DOM元素,它将自动转换为一个WebElement对象。
简单的例子,在页面上加载了jQuery:
element = driver.execute_script("return $('.cheese')[0]")
在页面上的每个标签查找全部输入元素:
labels = driver.find_elements_by_tag_name("label") inputs = driver.execute_script( "var labels = arguments[0], inputs = []; for (var i=0; i < labels.length; i++){" + "inputs.push(document.getElementById(labels[i].getAttribute('for'))); } return inputs;", labels)
用户输入-填写表单
咱们已经看到了如何将文字输入到一个文本或文本字段,但其余元素?您能够“切换”复选框的状态,你可使用“点击”设置相似选择的选项标记。处理SELECT标签是否是太糟糕:
select = driver.find_element_by_tag_name("select") allOptions = select.find_elements_by_tag_name("option") for option in allOptions: print "Value is: " + option.get_attribute("value") option.click()
找到页面上第一个“select”的元素,并经过每一个选项依次循环,打印出它们的值。你会发现,这不是最有效处理SELECT元素的方式。在webdriver的支持类中,有一个名为“select”,它提供了一些有用的方法,来处理这些交互。
# available since 2.12 from selenium.webdriver.support.ui import Select select = Select(driver.find_element_by_tag_name("select")) select.deselect_all() select.select_by_visible_text("Edam")
从页面上第一个选择开始取消全部选项,从第一个选择页面上的全部选项,而后选择显示的文本与“Edam” 的选项。
当你完成填写表格,你可能要提交。咱们须要找到“提交”按钮,而后单击它:
driver.find_element_by_id("submit").click()
另外,有方便的方法能够在webdriver的每一个元素上的“提交”。若是调用此表单内的元素,webdriver经过的DOM按顺序找到封闭的形式,而后调用该提交。若是该元素不是一种形式,那么会抛出NoSuchElementException异常:
element.submit()
移动Windows和框架(Frames)
一些web应用程序有许多框架或多个窗口。经过webdriver的“switchTo”方法能够对他们呢进行移动操做。
driver.switch_to_window("windowName")
调用驱动程序如今解释为被定向到特定的窗口。可是如何知道窗口的名字?以JavaScript或连接的方式打开它看看:
<a href="somewhere.html" target="windowName">Click here to open a new window</a>
另外,你也能够经过“window handle”的“switchTo().window()”方法。认识到这一点,那么就能够遍历全部打开的窗口,像这样:
for handle in driver.window_handles: driver.switch_to_window(handle)
还能够切换从frames到frames(或到iframe中):
driver.switch_to_frame("frameName")
访问子frames由一个圆点分隔的路径,而且能够经过其索引指定frames。是:
driver.switch_to_frame("frameName.0.child")
would go to the frame named “child” of the first subframe of the frame called “frameName”.All frames are evaluated as if from *top*. -----实在不知道这个怎么翻译
弹出对话框
Selenium 2.0测试版一开始,内置有处理弹出对话框支持。当你触发一个动做,打开一个弹出框,您将获得如下提醒:
alert = driver.switch_to_alert() # usage: alert.dismiss(), etc.
这将返回当前打开的警报对象。有了这个对象,你如今能够接受,拒绝,读取其内容,甚至类型会获得一个提示。这个接口一样适用警告,确认和提示。参考到的JavaDoc 或RubyDocs的的更多信息。
导航:历史和位置
此前,咱们介绍了webdriver的导航使用“get”命令
(driver.get(“http://www.example.com”)),咱们在有些状况下是要用到导航栏前进和头退功能:
driver.get("http://www.example.com") # python doesn't have driver.navigate
重申:“navigate().to()” 和 “get()” 的效果是同样的。一个只是不少比其余更容易输入!
你能够随意的使用浏览器历史记录中后退和前进功能:
driver.forward() driver.back()
请注意,此功能彻底依赖于底层浏览器。当你调用这些方法时,在不一样的浏览器下可能会发生意想不到的事情
Cookies
你可能会很是感兴趣了解如何使用Cookie。首先,你须要知道cookie有效期。若是您想先预设的cookie,而后再开始与网站进行交互,你的主页很大/且须要一段时间来加载,一个办法是找到一个更小的网页来代替,一般404页小(http://example.com/some404page)
#转到正确的域 driver.get("http://www.example.com") #如今在这里的整个域设置的cookie, #这里的cookie的名称是'key',它的值是'value'的 driver.add_cookie({'name':'key', 'value':'value', 'path':'/'}) # additional keys that can be passed in are: # 'domain' -> String, # 'secure' -> Boolean, # 'expiry' -> Milliseconds since the Epoch it should expire. # 如今的输出当前URL的全部可用的cookies for cookie in driver.get_cookies(): print "%s -> %s" % (cookie['name'], cookie['value']) # You can delete cookies in 2 ways # By name driver.delete_cookie("CookieName") # Or all of them driver.delete_all_cookies()
更改用户代理
这是很容易与Firefox的驱动程序:
拖放
下面是一个例子使用执行拖放动做类。本地事件事件须要被激活。
from selenium.webdriver.common.action_chains import ActionChains element = driver.find_element_by_name("source") target = driver.find_element_by_name("target") ActionChains(driver).drag_and_drop(element, target).perform()
驱动程序的细节和权衡
Selenium webdriver的驱动程序
参考:http://www.cnblogs.com/fnng/archive/2012/02/10/2345187.html
webdriver的对于不一样浏览器经过不一样的接口实现;下面介绍这几种实现方式:
HtmlUnit的驱动程序
这是目前最快,最轻量级的实施webdriver测试。正如它的名字所暗示的,这是基于HtmlUnit的。HtmlUnit是一个java实现基于web浏览器,没有图形用户界面。对于任何语言绑定(Java之外)Selenium服务器须要使用此驱动程序。
用法
driver = webdriver.Remote("http://localhost:4444/wd/hub", webdriver.DesiredCapabilities.HTMLUNIT))
优势
· 在Webdriver执行自动化最快的方式
· 一个纯Java的解决方案,所以它是独立于平台的。
· 支持JavaScript的
缺点
· 模拟其余浏览器的JavaScript行为(见下文)
HtmlUnit驱动器JavaScript
没有流行的浏览器使用JavaScript引擎,使用HtmlUnit(Rhino)。
若是你使用HtmlUnit测试JavaScript ,相比其余浏览 结果可能会不同。
当咱们说“JavaScript”,其实咱们说的是“JavaScript和DOM”。虽然DOM是由W3C定义的,每一个浏览器都有本身特色和差别,HtmlUnit 有一套完整的实现DOM的方案,能很好的支持JavaScript ,但有别与其余浏览器,和W3C标准的主流浏览器的DOM的实现存在差别,尽管其模仿其有他浏览器的能力。
在webdriver ,咱们选择使用HtmlUnit来测试Javascript ,不过这样存在问题和风险,但有愈来愈多的网站依赖于JavaScript ,咱们采起了保守的作法,HtmlUnit默认状况下禁用JavaScript 。在webdriver的HtmlUnit的每一个版本,咱们从新评估这一决定:咱们但愿在一些点上HtmlUnit的默认状况下启用JavaScript。
启用JavaScript
启用JavaScript的支持是很容易的:
driver = webdriver.Remote("http://localhost:4444/wd/hub", webdriver.DesiredCapabilities.HTMLUNITWITHJS)
这将致使HtmlUnit的驱动程序默认状况下,模拟火狐3.6的JavaScript进行处理。
Firefox Driver
用Firefox的插件来控制火狐浏览器,firefox 配置文件使用selenium.xpi(插件)。默认状况下,须要修改一些设置(see the source to see which ones),火狐驱动是可以运行在Windows,Mac,Linux上进行测试。目前在版本3.6,10(这个版本早过期了)
用法
driver = webdriver.Firefox()
优势
· 在一个真正的浏览器上运行,并支持JavaScript的
· 速度比Internet Explorer的驱动程序快
缺点
· 比HtmlUnit的驱动程序慢
修改火狐简介
假设你想要修改的用户代理字符串(如上述),但你已经有了一个欺骗Firefox的配置文件,它包含许多有用的扩展。有两种方式得到此配置文件。假设使用Firefox的配置文件管理器(火狐 ProfileManager),已建立配置:
另外,若是配置文件还没有在Firefox注册:
当咱们正在开发firefox 启动的特性,咱们可以正常使用。
正如咱们在Firefox Driver,开发功能,咱们可以使用。例如,直到咱们感受本机事件为Linux上的Firefox是稳定的,他们是默认状况下禁用。要启用它们:
profile = webdriver.FirefoxProfile() profile.native_events_enabled = True driver = webdriver.Firefox(profile)
Internet Explorer Driver
该驱动程序控制.dll,于是只适用于Windows操做系统。每一个selenium释放它的核心功能在xp下测试IE版本6,7和8,在Windows7下测试IE 9。
用法
driver = webdriver.Ie()
优势
· 运行在一个真正的浏览器支持JavaScript与最终用户看到的全部的行为一致
缺点
· 显然,Internet Explorer Driver只能在Windows上工做!
· 相对缓慢(尽管仍然是至关快速的)
· 自己不支持XPath的大多数版本。自动注入,这是明显慢于其余浏览器和进行比较时,在同一浏览器的CSS选择器变慢。
· 自己不支持CSS版本6和7。
· CSS选择器在IE 8和9是本地的,但这些浏览器不彻底支持CSS3
信息
维基页面的最早进的最新信息,请参阅Internet Explorer的部分。请特别注意所需的配置部分。
Chrome驱动
Chrome驱动程序维护/支持Chrome 项目自己。webdriver的工做与Chrome经过的chromedriver二进制(Chrome项目的下载页面上找到)。你须要有两个chromedriver和安装一个版本的Chrome浏览器。为了webdriver的自动找到,chromedriver须要要放在系统的路径上。Chrome浏览器自己由chromedriver在默认安装路径找到。这些均可以经过环境变量覆盖。 有关更多信息,请参阅维基。
用法
driver = webdriver.Chrome()
优势
· 在一个真正的浏览器上运行,并支持JavaScript的
· 由于Chrome是基于Webkit的浏览器,Chrome Driver会容许您验证您的网站在Safari的测试效果。须要注意的是,由于浏览器使用其本身的V8 JavaScript引擎,而不是Safari浏览器的Nitro引擎,JavaScript的执行可能会有所不一样。
缺点
· 比HtmlUnit的驱动程序慢
·
获取与Chrome驱动程序运行
铬驱动程序可执行文件下载 ,并按照其余的wiki页面上的说明
Opera Driver
见歌剧院驱动器在上使用Opera驱动程序的信息的selenium维基wiki文章。
iPhone Driver
查看iPhone的驱动selenium维基上使用Mac的iOS驱动程序的信息,wiki文章。
Android Driver
查看Android的驱动程序 硒selenium维基采用了Android驱动程序的信息,wiki文章。
混合使用webdriver和RC技术
Webdriver替换selenium RC
webdriver的Java版本的selenium RC API提供了一种实现。这意味着,你可使用Selenium-RC API和使用底层webdriver的技术。这主要是用于向后兼容。它容许那些使用selenium RC API的用户使用webdriver覆盖现有的测试套件。它提供帮助缓解迁移到selenium webdriver。此外,容许一我的使用这两个API,在相同的测试代码。
Selenium webdriver的使用是这样的:
优势
· webdriver的和selenium的API容许并排存在
· webdriver的迁移管理机制提供了一个简单的Selenium RC API
· 不须要独立的Selenium RC服务器的运行
缺点
· 不能支持每个方法
· 更多先进的selenium使用(using “browserbot” or other built-in JavaScript methods from Selenium Core)可能没法正常工做
· 因为底层实现差别,有些方法可能会比较慢
备份webdriver与selenium
webdriver的尽量多兼容selenium RC对浏览器的支持,同时仍然提供支持使用webdriver的API,因此为了您能够利用SeleneseCommandExecutor
Safari是支持这种方式,用下面的代码(确保禁用弹出窗口拦截功能):
这种方法目前有一些主要限制,尤为是findElements并不如预期般运做。此外,繁重的驱动浏览器,由于咱们使用的是selenium 的核心,你的JavaScript沙箱限制。
运行独立Selenium服务器使用RemoteDrivers
从selenium 的下载页下载服务器独立<version>.jar和可选的IEDriverServer。若是您打算使用Chrome,从Google Code上下载。
拆开IEDriverServer和(或)chromedriver,并把它们在$ PATH /%PATH% - Selenium服务器上的一个目录,这是应该可以IE / Chrome的处理请求,而无需额外的修改。
启动服务器的命令行
java -jar <path_to>/selenium-server-standalone-<version>.jar
若是你想使用原生的事件功能,代表在命令行上的选项
Dwebdriver.enable.native.events = 1
对于其余命令行选项,执行
java -jar <path_to>/selenium-server-standalone-<version>.jar -help
为了正常工做,应该容许如下端口传入的TCP链接:4444,7054-5(or twice as many ports as the number of concurrent instances you plan to run)。在Windows下,你可能须要以及疏通各类应用。