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 WebDriver_第1张图片
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更合适。

如果待测元素的源码如下所示,我们该如何定位呢:

...

解释:此处我们假设该元素是一个按钮。该元素的 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 页面源码,我们如何使用该方法定位元素呢:

Cheddar
Gouda

解释:该元素的 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 页面源码,我们如何使用该方法定位元素呢:

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 识别某个元素的概率很低,例如我们打开任意一个页面,查看前端都会发现大量的

等等 tag。除非一个页面只有这一个没有重复的 tag,比如上述示例,