Selenium WebDriver

Selenium 官网
Selenium WebDriver官网
webdriver实用指南python版本


WebDriver原理
WebDriver是按照Server-Client 的模式设计的。

Server就是 Remote Server,可以是任意的浏览器。当我们的脚本启动浏览器后,该浏览器就是Remote Server,她的职责就是等待 Client 发送请求并做出响应。

Client 端简单说就是我们写的测试脚本。脚本中的一些行为比如打开浏览器,跳转到指定的 URL 等操作就是以 http 请求的方式发送给被测试的浏览器,也就是Remote Server。Remote Server接受请求,执行相应操作,并在 Response中返回执行状态、返回值等信息。

Selenium 组成

Introducing WebDriver


作者注:WebDriver 可以看作是Selenium-RC替代品。所以现在学习 Selenium 就不需要花时间专注于Selenium-RC了。

Selenium 2.0的主要新特性是WebDriver API的集成。WebDriver旨在提供一个更简单、更简洁的编程接口,以解决Selenium-RC API的一些限制。Selenium-WebDriver是为了更好地支持动态web页面而开发的,页面的元素在没有页面本身被重新加载的情况下可能会发生变化。WebDriver的目标是提供一个设计良好的面向对象的API,为现代高级web应用程序测试问题提供改进的支持。

Selenium RC(Selenium 3.0版本移除了该模块,以后还是使用 WebDriver 进行脚本的编写) 由Clent Libraies 和 Selenium Server组成:

Selenium Libraies 用于编写测试脚本,支持多种不同的主流开发语言,用来控制Selenium Server.

Selenium Server 则负责控制浏览器的行为,而Selenium Server 又由三部分组成:

  • Selenium Core:被Selenium Server 嵌入到浏览器页面中,是一堆的JavaScript 函数的集合,通过这些JavaScript函数来实现对浏览器的操作。

  • Launcher:用于启动浏览器,把Selenium Core加载到浏览器页面当中,并把浏览器的代理设置Selenium Server 的Http Proxy。

  • Http Proxy:Selenium Server的http代理。

  

How Does WebDriver ‘Drive’ the Browser Compared to Selenium-RC?


Selenium-WebDriver使用每个浏览器对自动化的本地支持直接调用浏览器。这些直接调用是如何生成的,它们支持的特性取决于您使用的浏览器。本章稍后将提供关于每个“浏览器驱动程序”的信息。

对于那些熟悉Selenium-RC的人来说,这与您所习惯的完全不同。Selenium-RC对每个支持的浏览器都使用相同的方法。它在浏览器加载时将javascript函数注入浏览器,然后使用javascript在浏览器中驱动AUT。WebDriver不使用这种技术。同样,它直接驱动浏览器使用内置的支持自动化的浏览器。

  

WebDriver and the Selenium-Server


您可能,也可能不需要Selenium服务器,这取决于您打算如何使用Selenium- webdriver。如果您的浏览器和测试都运行在同一台机器上,并且您的测试只使用WebDriver API,那么您就不需要运行selenium服务器;WebDriver将直接运行浏览器。

不过,有一些原因可以使用selenium服务器和Selenium-WebDriver。

  • 您正在使用Selenium-Grid在多台机器或虚拟机(vm)上分发测试。
  • 您希望连接到具有特定浏览器版本的远程机器,而不是当前机器上的。
  • 您没有使用Java绑定(例如Python、c#或Ruby),并希望使用 HtmlUnit Driver

Setting Up a Selenium-WebDriver Project


安装Selenium意味着在开发中建立项目,这样您就可以使用Selenium编写程序。如何做到这一点取决于您的编程语言和开发环境。
这里只介绍如何将Selenium添加到Python环境
pip install selenium
或者是:
pip3 install selenium

Pip需要安装 pip, Pip也依赖于 setuptools

至于如何将Selenium添加到其他语言环境中,请查阅Selenium WebDriver官网

至于已经在使用 Selenium1.0的同学们如何转为使用Selenium WebDriver。请看官网介绍

  

Introducing the Selenium-WebDriver API by Example


WebDriver是一种用于自动化web应用程序测试的工具,特别是用于验证它们是否按预期工作。它的目标是提供一个友好的API,易于探索和理解,比Selenium-RC (1.0) API更容易使用,这将有助于使您的测试更容易阅读和维护。它不依赖于任何特定的测试框架,因此它可以在单元测试项目中或从简单的旧的“main”方法中使用。本节介绍WebDriver的API,并帮助您熟悉它。如果您还没有建立一个WebDriver项目,那就开始吧。这在前面的小节中描述过,设置了一个Selenium-WebDriver项目。

一旦您的项目建立起来,您可以看到WebDriver就像任何普通的库一样:它是完全自包含的,而且您通常不需要记住在使用它之前启动任何其他进程或运行任何安装程序,而不是使用Selenium-RC的代理服务器。

注意: 使用 ChromeDriver, Opera Driver, Android Driver 以及 iOS Driver需要额外配置

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")

# the page is ajaxy so the title is originally this:
print driver.title

# 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()

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()

其他脚本语言示例请参考

  

Selenium-WebDriver API Commands and Operations


  Fetching a Page(获取某个页面)


你可能想要做的第一件事是导航到一个页面。通常的方法是通过调用get:
driver.get("http://www.google.com")

该脚本为 Python 脚本,其他语言脚本请参考

依赖于几个因素,包括操作系统/浏览器组合,WebDriver可能会等待页面加载。在某些情况下,WebDriver可以在页面完成甚至开始加载之前返回控件。为了确保健壮性,您需要等待在页面中使用 Explicit and Implicit Waits
解释:因为网络环境的因素,每个页面每次加载的时间会有所不同,如果在某一个页面加载出来之前,脚本即执行该页面的某一个元素,则会报错。所以为了确保页面已经加载完毕再执行,所以我们会在必要的时候使用 wait 命令。

  Locating UI Elements (WebElements)


在WebDriver中定位元素可以在WebDriver实例本身或WebElement上完成。每个语言绑定公开一个 “Find Element” and “Find Elements” 方法。前者返回与查询匹配的WebElement对象,如果不能找到该元素,则抛出异常。后者返回一个WebElements列表,如果没有DOM元素匹配查询,则可能为空。

“Find”方法采用名为“By”的定位器或查询对象。下面列出了“策略”。

作者注:DOM属性
DOM 是 W3C(万维网联盟)的标准。
属性是节点(HTML 元素)的值,您能够获取或设置。

  By ID


这是定位一个元素最有效的方法。UI开发人员所犯的常见错误是在页面上有非惟一id,或者自动生成id,这两个都应该避免。html元素上的类比自动生成的id更合适。

如果待测元素的源码如下所示,我们该如何定位呢:
<div id="coolestWidgetEvah">...</div>
解释:此处我们假设该元素是一个按钮。该元素的 id 即为coolestWidgetEvah。就可以通过 id 定位到该元素。除非某个元素没有 id 这个属性,一般我们都使用 id 定位元素。

以下使用 id定位 元素为 Python 脚本示例:

element = driver.find_element_by_id("coolestWidgetEvah")

或者

from selenium.webdriver.common.by import By
element = driver.find_element(by=By.ID, value="coolestWidgetEvah")

解释:通过这两个方法均可以定位到该按钮,并将该方法返回的值赋值给变量 element,以便进行其他操作。

其他语言脚本示例请参考

  By Class Name


本例中的“类”是指DOM元素上的属性。通常在实际使用中,有许多具有相同类名的DOM元素,因此,查找第一个元素时,找到多个元素成为更实际的选择。

类似下面的待测 web 页面源码,我们如何使用该方法定位元素呢:
<div class="cheese"><span>Cheddar</span></div><div class="cheese"><span>Gouda</span></div>
解释:该元素的 class(类)即 cheese。

Python 脚本如下:

cheeses = driver.find_elements_by_class_name("cheese")

或者

from selenium.webdriver.common.by import By
cheeses = driver.find_elements(By.CLASS_NAME, "cheese")

其他语言脚本请参考

  By Tag Name


元素的DOM标记名。
类似下面的待测 web 页面源码,我们如何使用该方法定位元素呢:
<iframe src="..."></iframe>
Python 示例:

frame = driver.find_element_by_tag_name("iframe")

或者

from selenium.webdriver.common.by import By
frame = driver.find_element(By.TAG_NAME, "iframe")

其他脚本语言示例请参考

通过 tag 识别某个元素的概率很低,例如我们打开任意一个页面,查看前端都会发现大量的<div>、<input>、<a>等等 tag。除非一个页面只有这一个没有重复的 tag,比如上述示例,<iframe>就是很少用的一个 tag,如果一个页面中只有这么一个<iframe>tag 那么就可以用 tag 定位。

  By Name


找到具有匹配名称属性的输入元素。
类似下面的待测 web 页面源码,我们如何使用该方法定位元素呢:
<input name="cheese" type="text"/>
以下为 Python 示例:

cheese = driver.find_element_by_name("cheese")
或者

from selenium.webdriver.common.by import By
cheese = driver.find_element(By.NAME, "cheese")

其他脚本语言示例请参考

  By Link Text


找到与可见文本匹配的链接元素。
类似下面的待测 web 页面源码,我们如何使用该方法定位元素呢:
<a href="http://www.google.com/search?q=cheese">cheese</a>>

以下为 Python 示例:

cheese = driver.find_element_by_link_text("cheese")

或者

from selenium.webdriver.common.by import By
cheese = driver.find_element(By.LINK_TEXT, "cheese")

比如百度主页顶部的一行链接,如图:

find_element_by_link_text("新闻").click().png

如果想要点击“新闻”这个链接,那么就使用这个定位方法。

其他脚本语言示例请参考

  By Partial Link Text


找到带有部分匹配可见文本的链接元素。

类似下面的待测 web 页面源码,我们如何使用该方法定位元素呢:
<a href="http://www.google.com/search?q=cheese">search for cheese</a>>

以下为 Python 示例:

cheese = driver.find_element_by_partial_link_text("cheese")

或者

from selenium.webdriver.common.by import By
cheese = driver.find_element(By.PARTIAL_LINK_TEXT, "cheese")

比如百度主页底部有一个比较长的链接,如图:


find_element_by_partial_link_text

这个链接的完整文本是“京公网安备11000002000001号”,我们使用部分文本,比如“京公网”就可以唯一确定是这个链接。此时就可以使用该定位方法。

  By CSS


顾名思义,它是css的定位策略。默认情况下使用本机浏览器支持,所以请参考w3c css selectors,以获得一般可用的css选择器列表。如果浏览器没有对css查询的本机支持,则使用 Sizzle。IE6、7和FF3.0目前使用Sizzle作为css查询引擎。

要注意的是,并非所有的浏览器都是相同的,有些css可能在一个版本中工作,但在另一个版本中可能无效。

比如下面查找“cheese”这个元素:

<div id="food"><span class="dairy">milk</span><span class="dairy aged">cheese</span></div>

python脚本示例:

cheese = driver.find_element_by_css_selector("#food span.dairy.aged")

解释一下这个定位方法:

  • #表示通过 id 属性定位元素,因为 food 是一个 id 属性值,所以前面加一个#号;
  • 通过标签名定位元素前面不加任何符号标识,直接使用标签名即可,因为 span 是一个标签名,所以前面什么都不加;
  • . 表示通过 class 属性定位元素,因为 dairy 是一个 class 属性值,所以前面加一个.号。

这个脚本用的是多种方式的组合。通过一级级标签进行最终的定位。我们还以百度主页为例进行举例说明。

  • 比如通过 class 属性定位到输入框 这个元素:
    find_element_by_css_selector(".s_ipt")

  • 比如通过 id 属性定位到输入框这个元素:
    find_element_by_css_selector("#kw")

  • 比如通过标签名定位(当然这里不适用,标签名<input>不唯一):
    find_element_by_css_selector("input")
    通过组合定位就是:
    find_element_by_css_selector("input#kw")
    注意:这里 class 和 id 两个属性是同一级标签下的属性,只使用一个。

为了更精确的定位,我们还可以使用刚精确的定位方式:
find_element_by_css_selector("div span input#kw")
这种组合方式还有很多,再举一例:

browser.find_element_by_css_selector("form.fm span.bg.s_ipt_wr.quickdelete-wrap input.s_ipt").send_keys(u"简书")

注意: 最后在输入框输入汉字的时候在汉字前加了一个字母 u,如果不加则会造成汉字无法识别的错误

或者

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 定位)。

Driver Tag and Attribute Name Attribute Values Native XPath Support
HtmlUnit Driver Lower-cased As they appear in the HTML Yes
Internet Explorer Driver Lower-cased As they appear in the HTML No
Firefox Driver Case insensitive As they appear in the HTML Yes

这是一个有点抽象的东西,所以对于下面这段HTML:

<input type="text" name="example" />
<INPUT type="text" name="other" />

python 脚本示例:

inputs = driver.find_elements_by_xpath("//input")

或者

from selenium.webdriver.common.by import By
inputs = driver.find_elements(By.XPATH, "//input")

将会找到以下的匹配数:

XPath expression HtmlUnit Driver Firefox Driver Internet Explorer Driver
//input 1 (“example”) 2 2
//INPUT 0 2 0

有时,HTML元素不需要显式地声明属性,因为它们将默认为已知值。例如,“input”标签不需要“type”属性,因为它默认为“text”。在WebDriver中使用xpath时的经验法则是,您不应该期望能够与这些隐式属性相匹配。

这里介绍一下“绝对路径定位”方法,这个方法在定位元素走投无路的时候或许能帮助你。我们还是以百度首页的输入框为例,如下图:


绝对路径定位

如果这个输入框元素的属性没有 id,没有 class,没有name。咋办,使用 tag 定位?你可以看到这个页面不止一个<input>,不具有唯一性,所以无法使用 tag 定位。此时就可以使用绝对路径定位。脚本如下:
find_element_by_xpath("/html/body/div/div[1]/div/div/div/form/span/input")

看起来就有点晕,我来解释一下。

这里是通过标签定位,必须要从<html>开始。<html>的下一级标签有<head>和<body>,这两个标签是平级的,没有父子之分,因为我们要定位的元素在标签<body>下,所以<html>之后是<body>。<body>之后又有两个平级标签<script>和<div>,我们选择<div>。但是这个<div>标签之后有多个平级标签<div>,上面截图没有体现,看下图:


CF8B84DD-ED3E-4588-A4C2-EFE53252F7B1.png


这个标签下有很多平级标签均未<div>,而我们要找的是第一个<div>,所以是<div>[1]。以此类推,直达定位到目标元素。

注意:这种定位方法不到万不得已不使用,因为一旦页面有一点改动,定位就可能会出错。

  Using JavaScript


您可以执行任意的javascript来找到一个元素,只要返回一个DOM元素,它就会自动转换成一个WebElement对象。

在具有jQuery的页面上的简单示例:

java示例:

WebElement element = (WebElement) ((JavascriptExecutor)driver).executeScript("return $('.cheese')[0]");

python 示例:
element = driver.execute_script("return $('.cheese')[0]")

查找页面上每个标签的所有输入元素:

java示例:

List<WebElement> labels = driver.findElements(By.tagName("label"));
List<WebElement> inputs = (List<WebElement>) ((JavascriptExecutor)driver).executeScript(
    "var labels = arguments[0], inputs = []; for (var i=0; i < labels.length; i++){" +
    "inputs.push(document.getElementById(labels[i].getAttribute('for'))); } return inputs;", labels);

python 示例:

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)

  Getting text values


人们通常希望检索元素中包含的innerText值。这会返回单个字符串值。注意,这只会返回页面上显示的可见文本。

python 示例:

element = driver.find_element_by_id("element_id")
element.text

  User Input - Filling In Forms


我们已经看到了如何将文本输入到文本区域或文本字段中,但是其他元素又如何呢?您可以“切换”复选框的状态,您可以使用“click”设置一些类似于选择的选项标记。处理选择标签并不是很糟糕:

Python 脚本示例:

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”的类,它提供了与这些类交互的有用方法。

python

# 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")

这将从页面上的第一个SELECT中取消所有选项,然后选择带有“Edam”的显示文本的选项。

填写完表单后,您可能需要提交它。一种方法是找到“提交”按钮并点击它:

python

driver.find_element_by_id("submit").click()

Alternatively, WebDriver has the convenience method “submit” on every element. If you call this on an element within a form, WebDriver will walk up the DOM until it finds the enclosing form and then calls submit on that. If the element isn’t in a form, then the NoSuchElementException will be thrown:

python

element.submit()

  Moving Between Windows and Frames


一些web应用程序有许多框架或多个窗口。WebDriver支持使用“切换”方法在指定的窗口之间移动:

driver.switch_to.window("windowName")

所有对驱动程序的调用将被解释为指向特定的窗口。但是你怎么知道窗户的名字呢?看一下打开的javascript或链接:

<a href="somewhere.html" target="windowName">Click here to open a new window</a>

或者,您可以将“窗口句柄”传递给“切换().window()”方法。知道了这一点,就可以遍历每个打开的窗口:

python

for handle in driver.window_handles:
    driver.switch_to.window(handle)

作者注:HANDLE(句柄)是Windows操作系统中的一个概念。在Windows程序中,有各种各样的资源(窗口、图标、光标等),系统在创建这些资源时会为它们分配内存,并返回标示这些资源的标示号,即句柄。(摘自互动百科)

  Popup Dialogs


从Selenium 2.0 beta 1开始,构建了支持处理弹出对话框的支持。在您触发一个打开弹出窗口的操作之后,您可以通过以下方式访问警报:
python

alert = driver.switch_to.alert
# usage: alert.dismiss(), etc.

这将返回当前打开的警告对象。通过这个对象,您现在可以接受、解散、读取它的内容,甚至可以键入一个提示符。这个接口在警报、确认和提示上同样有效。更多信息请参考JavaDocs或RubyDocs。

  Navigation: History and Location


早些时候,我们使用“get”命令(driver.get(“http://www.example.com”)或driver.Url=“http://www.example.com”在c#中导航到一个页面。如您所见,WebDriver有许多较小的、面向任务的接口,导航是一项有用的任务。因为加载页面是一个基本的要求,所以在主WebDriver接口上执行这个操作的方法,但是它只是一个同义词:

python

driver.get("http://www.example.com")  # python doesn't have driver.navigate

重申:“导航(). To()”和“get()”做完全相同的事情。一个人比另一个更容易打字!

“导航”界面也暴露了在浏览器的历史中来回移动的能力:

python

driver.forward()
driver.back()

请注意,此功能完全依赖于底层浏览器。如果你习惯了一个浏览器的行为,那么你调用这些方法时可能会发生意想不到的事情。

  Cookies


在我们开始下一步内容之前,您可能会对如何使用cookie感兴趣。首先,您需要在cookie将有效的域上。如果你想在开始与网站交互之前预设cookie,而你的主页是大的/需要一段时间来加载另一种选择,那就是在网站上找到一个较小的页面(通常是404页面很小,例如http://example.com/some404page)。

Python

# Go to the correct domain
driver.get("http://www.example.com")

# Now set the cookie. Here's one for the entire domain
# the cookie name here is 'key' and its value is '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.

# And now output all the available cookies for the current URL
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()

  Changing the User Agent


这对于Firefox Driver来说很简单:

python

profile = webdriver.FirefoxProfile()
profile.set_preference("general.useragent.override", "some UA string")
driver = webdriver.Firefox(profile)

  Drag And Drop


这里有一个使用action类来执行拖放操作的示例。必须启用本地事件。

python

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()

  

Driver Specifics and Tradeoffs


Selenium-WebDriver’s Drivers


WebDriver是测试应该编写的关键接口的名称,但是有几个实现。这些包括:
  HtmlUnit Driver


这是目前最快速、最轻量级的WebDriver实现。顾名思义,这是基于HtmlUnit的。HtmlUnit是一个没有GUI的基于java的WebBrowser实现。对于任何语言绑定(除了java), Selenium服务器都需要使用这个驱动程序。

    Usage


python

driver = webdriver.Remote("http://localhost:4444/wd/hub", webdriver.DesiredCapabilities.HTMLUNIT.copy())

    Pros


  • 最快的实现WebDriver
  • 纯Java解决方案,因此它是平台无关的。
  • 支持JavaScript.

    Cons


  • 模拟其他浏览器的JavaScript行为(见下面)

    JavaScript in the HtmlUnit Driver


没有一个流行的浏览器使用HtmlUnit (Rhino)使用的JavaScript引擎。如果您使用HtmlUnit测试JavaScript,结果可能与那些浏览器有很大不同。

当我们说“JavaScript”时,实际上是指“JavaScript和DOM”。虽然DOM是由W3C定义的,但是每个浏览器都有自己的特性和在DOM的实现上的差异,以及JavaScript如何与DOM交互。HtmlUnit有一个令人印象深刻的完整实现使用JavaScript DOM和具有良好的支持,但它是没有不同于其他任何浏览器:它有自己的怪癖和差异来自W3C标准和主流浏览器的DOM实现,尽管其模仿其他浏览器的能力。

有了WebDriver,我们必须做出选择;我们是否启用了HtmlUnit的JavaScript功能,并运行那些只出现在那里的问题的团队的风险,或者我们是否禁用了JavaScript,知道有越来越多的站点依赖于JavaScript?我们采用了保守的方法,默认情况下在使用HtmlUnit时禁用了支持。随着WebDriver和HtmlUnit的每个版本的发布,我们重新评估这个决定:我们希望在HtmlUnit上默认启用JavaScript。

    Enabling JavaScript


If you can’t wait, enabling JavaScript support is very easy:

Python

driver = webdriver.Remote("http://localhost:4444/wd/hub", webdriver.DesiredCapabilities.HTMLUNITWITHJS)

这将导致HtmlUnit驱动程序在默认情况下模拟Firefox 3.6的JavaScript处理。

  Firefox Driver

使用Firefox插件控制 Firefox浏览器。使用的Firefox配置文件从安装在机器上的内容剥离出来,只包含了Selenium WebDriver。xpi(插件)。默认情况下,一些设置也会发生变化(参见源代码,看看哪些是Firefox驱动程序),Firefox驱动程序可以在Windows、Mac和Linux上进行测试。目前版本3.6, 10, latest - 1, latest。

    Usage


python

driver = webdriver.Firefox()

    Pros


    Cons


    修改Firefox配置文件


假设您想修改用户代理字符串(如上所示),但是您已经得到了一个包含几十个有用扩展的Firefox配置文件。获取这个概要文件有两种方法。假设该配置文件是使用Firefox的配置文件管理器(Firefox -ProfileManager)创建的:

java

ProfilesIni allProfiles = new ProfilesIni();
FirefoxProfile profile = allProfiles.getProfile("WebDriver");
profile.setPreferences("foo.bar", 23);
WebDriver driver = new FirefoxDriver(profile);

当我们在Firefox Driver中开发特性时,我们就暴露了使用它们的能力。例如,在我们感觉本地事件在Firefox中是稳定的Linux,在默认情况下它们是禁用的。使他们:

python

profile = webdriver.FirefoxProfile()
profile.native_events_enabled = True
driver = webdriver.Firefox(profile)

    Info


请参阅wiki页面中的Firefox部分,了解最新的信息。

  Internet Explorer Driver

InternetExplorerDriver是一个独立的服务器,它实现了WebDriver的有线协议。这个驱动程序已经测试了ie7、8、9、10和11,并在Vista、Windows 7、Windows 8和Windows 8.1的适当组合上进行了测试。截至2014年4月15日,IE 6不再受支持。

驱动程序支持运行32位和64位版本的浏览器。如何确定在启动浏览器时使用哪个“bit-ness”取决于IEDriverServer的哪个版本。exe。如果是32位版本的IEDriverServer。exe启动后,IE的32位版本将启动。同样,如果IEDriverServer的64位版本。exe启动,将启动64位版本IE。

    Usage


Python

driver = webdriver.Ie()

    Pros(优点)


  • 在真正的浏览器中运行并支持Javascript。

    Cons(缺点)


  • 很明显,InternetExplorerDriver只会在Windows上运行!
  • 比较慢(虽然还是很时髦!)

    Info


查看wiki页面的Internet Explorer部分 ,了解最新的信息。请特别注意所需的配置部分。

  

  ChromeDriver

ChromeDriver由Chromium项目维护/支持。WebDriver通过chromedriver二进制文件(在chromium项目的下载页面上找到)与Chrome合作。你需要安装chromedriver和chrome浏览器的版本。chromedriver需要放在系统的路径上,以便WebDriver自动发现它。chromedriver在默认安装路径中发现了Chrome浏览器本身。这些都可以被环境变量覆盖。更多信息请参考 the wiki(维基百科)。

    Usage


Python

driver = webdriver.Chrome()

    Pros(优点)


  • 在真正的浏览器中运行并支持JavaScript。

  • 因为Chrome是一个基于webkit的浏览器,ChromeDriver可以让你验证你的网站在Safari中运行。注意,由于Chrome使用的是自己的V8 JavaScript引擎而不是Safari的Nitro引擎,JavaScript的执行可能会有所不同。

    Cons(缺点)


  

    Info


See our wiki,了解最新的信息。更多信息也可以在 downloads page
找到。

  

    Getting running with ChromeDriver


下载ChromeDriver可执行文件,并遵循 wiki page上的其他说明。

  

  Opera Driver

See the Opera Driver wiki article in the Selenium Wiki for information on using the Opera Driver.

  

  iOS Driver

See either the ios-driver or appium projects.

  

  Android Driver

See the Selendroid project

  

Alternative Back-Ends: Mixing WebDriver and RC Technologies


  WebDriver-Backed Selenium-RC


WebDriver的Java版本提供了Selenium-RC API的实现。这意味着您可以使用Selenium-RC API使用底层的WebDriver技术。这主要是为向后兼容性提供的。它允许使用Selenium-RC API的现有测试套件在覆盖下使用WebDriver。它提供了帮助简化迁移到Selenium-WebDriver的路径。同样,这允许在相同的测试代码中同时使用两个api。

Selenium-WebDriver是这样使用的:

java

// You may use any WebDriver implementation. Firefox is used here as an example
WebDriver driver = new FirefoxDriver();

// A "base url", used by selenium to resolve relative URLs
 String baseUrl = "http://www.google.com";

// Create the Selenium implementation
Selenium selenium = new WebDriverBackedSelenium(driver, baseUrl);

// Perform actions with selenium

selenium.open("http://www.google.com");
selenium.type("name=q", "cheese");
selenium.click("name=btnG");

// Get the underlying WebDriver implementation back. This will refer to the
// same WebDriver instance as the "driver" variable above.
WebDriver driverInstance = ((WebDriverBackedSelenium) selenium).getWrappedDriver();

//Finally, close the browser. Call stop on the WebDriverBackedSelenium instance
//instead of calling driver.quit(). Otherwise, the JVM will continue running after
//the browser has been closed.
selenium.stop();

    优点(Pros)


  • 允许WebDriver和Selenium api共存。
  • 提供从Selenium RC API到WebDriver的管理迁移的简单机制。
  • 不需要运行独立的Selenium RC服务器吗?

    缺点(Cons)


  • 不能实现每个方法
  • 更高级的Selenium使用(使用“browserbot”或来自Selenium Core的其他内置JavaScript方法)可能不起作用。
  • 由于底层实现差异,一些方法可能会比较慢。

  Backing WebDriver with Selenium


WebDriver不像Selenium RC那样支持很多浏览器,所以为了在使用WebDriver API时提供支持,您可以使用SeleneseCommandExecutor。

以这种方式支持Safari,并使用以下代码(确保禁用弹出式阻塞):

java(官方文档只提供了 JAVA 示例):

DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setBrowserName("safari");
CommandExecutor executor = new SeleneseCommandExecutor(new URL("http://localhost:4444/"), new URL("http://www.google.com/"), capabilities);
WebDriver driver = new RemoteWebDriver(executor, capabilities);

目前,这种方法存在一些主要的局限性,尤其是findElements不像预期的那样工作。另外,由于我们使用Selenium Core来驱动浏览器,所以您受到JavaScript sandbox的限制。

  

运行独立的Selenium服务器,用于远程驱动程序(Running Standalone Selenium Server for use with RemoteDrivers)


Selenium的下载页面下载selenium-server-standalone-<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(或者是您计划运行的并发实例数量的两倍)。在Windows下,您可能还需要打开应用程序。

Additional Resources


你可以在 WebDriver’s wiki中找到更多的WebDriver资源。

当然,不要犹豫,在任何Selenium主题上进行internet搜索,包括Selenium- webdriver的驱动程序。有很多关于Selenium的博客,以及许多用户论坛上的帖子。另外,Selenium User’s Group是一个很好的资源。
http://groups.google.com/group/selenium-users

Next Steps


这一章简单地介绍了WebDriver及其一些关键功能。一旦熟悉了Selenium-WebDriver API,您就会想要学习如何构建可维护性、可扩展性和降低脆弱性的测试套件。大多数Selenium专家现在建议的方法是使用页面对象设计模式(Page Object Design Pattern)和可能的页面工厂(Page Factory)来设计测试代码。通过在Java和c#中提供一个PageFactory类,Selenium-WebDriver提供了支持。在 next chapter中,我们将介绍这一主题,以及其他高级主题。另外,对于该技术的高级描述,您可能需要查看 Test Design Considerations chapter。这两章都介绍了通过使测试代码更模块化编写更易于维护的测试的技术。

Next topic


WebDriver: Advanced Usage

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容