WEBDRIVER
The biggest change in Selenium recently has been the inclusion of the WebDriver API. Driving a browser natively as a user would either locally or on a remote machine using the Selenium server, it marks a leap forward in terms of browser automation.
Selenium WebDriver fits in the same role as RC did, and has incorporated the original 1.x bindings. It refers to both the language bindings and the implementations of the individual browser controlling code. This is commonly referred to as just WebDriver or sometimes as Selenium 2.
Selenium 1.0 + WebDriver = Selenium 2.0
- WebDriver is designed in a simpler and more concise programming interface along with addressing some limitations in the Selenium-RC API.
- WebDriver is a compact object-oriented API when compared to Selenium 1.0.
- It drives the browser much more effectively and overcomes the limitations of Selenium 1 that affected our functional test coverage, like the file upload or download, pop-ups, and dialogs barrier.
- WebDriver overcomes the limitation of Selenium RC's single-host origin policy.
DRIVER REQUIREMENTS
Through WebDriver, Selenium supports all major browsers on the market such as Chrom(ium), Firefox, Internet Explorer, Opera, and Safari. Where possible, WebDriver drives the browser using the browser's built-in support for automation, although not all browsers have official support for remote control.
WebDriver's aim is to emulate a real user's interaction with the browser as closely as possible. This is possible at varying levels in different browsers. For more details on the different driver idiosyncracies, please see Driver Idiosyncracies.
Even though all the drivers share a single user-facing interface for contolling the browser, they have slightly different ways of setting up browser sessions. Since many of the driver implementations are provided by third parties, they are not included in the standard Selenium distribution.
Driver instantiation, profile management, and various browser specific settings are examples of parameters that have different requirements depending on the browser. This section explains the basic requirements for getting you started with the different browsers.
Adding Executables to your PATH
Most drivers require an extra executable for Selenium to communicate with the browser. You can manually specify where the executable lives before starting WebDriver, but this can make your tests less portable, as the executables will need to be in the same place on every machine, or included within your test code repository.
By adding a folder containing WebDriver's binaries to your system's path, Selenium will be able to locate the additional binaries without requiring your test code to locate the exact location of the driver.
- Create a directory to place the executables in, like C:\WebDriver\bin or /opt/WebDriver/bin
- Add the directory to your PATH:
- On Windows - Open a command prompt as administrator and the run the following command to permanently add the directory to your path for all users on your machine:
setx /m path "%path%;C:\WebDriver\bin\"
- Bash users on macOS and Linux - In a terminal:
export PATH=$PATH:/opt/WebDriver/bin >> ~/.profile
- You are now ready to test your changes. Close all open command prompts and open a new one. Type out the name of one of the binaries in the folder you created in the previous step, e.g:
chromedriver
. If your PATH is configured correctly, you will see some some output relating to the startup of the driver:
Starting ChromeDriver 2.25.426935 (820a95b0b81d33e42712f9198c215f703412e1a1) on port 9515 Only local connections are allowed.
You can regain control of your command prompt by pressing Ctrl + C.
Quick reference
Browser
|
Supported OS
|
Maintained by
|
Download
|
Issue Tracker
|
Chromium/Chrome
|
Windows
macOS
Linux
|
Google
|
|
|
Firefox
|
Windows
macOS
Linux
|
Mozilla
|
|
|
Edge
|
Windows 10
|
Microsoft
|
|
|
Internet Explorer
|
Windows
|
Selenium Project
|
|
|
Safari
|
macOS El Capitan and newer
|
Apple
|
Built in
|
|
Opera
|
Windows
macOS
Linux
|
Opera
|
|
|
Chromium/Chrome
To drive Chrome or Chromium, you have to download chromedriver and put it in a folder that is on your system's path.
On Linux or macOS, this means modifying the PATH environmental variable. You can see what directories, separated by a colon, make up your system's path by executing the following command:
$ echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
To include chromedriver on the path if it isn't already, make sure you include the chromedriver binary's parent directory. The following line will set the PATH environmental variable its current content, plus an additional path added after the colon:
$ export PATH="$PATH:/path/to/chromedriver"
When chromedriver is available on your path, you should be able to execute the _chromedriver_ executable from any directory.
To instantiate a Chrome/Chromium session, you can do the following:
WebDriver driver = new ChromeDriver();
Remember that you have to set the path to the chromedriver executable. This is possible using the following line:
System.setProperty("webdriver.chrome.driver", "/path/to/chromedriver");
require "selenium-webdriver" driver = Selenium::WebDriver.for :chrome
The chromedriver is implemented as a WebDriver remote server that by exposing Chrome's internal automation proxy interface instructs the browser what to do.
Firefox
Starting with Selenium 3, Mozilla has taken over implementation of Firefox Driver, with geckodriver. The new driver for Firefox is called geckodriver and works with Firefox 48 and newer. Since the Firefox WebDriver is under development, the newer the Firefox version the better the support.
As geckodriver is the new default way of launching Firefox, you can instantiate Firefox in the same way as Selenium 2:
WebDriver driver = new FirefoxDriver();
require "selenium-webdriver" driver = Selenium::WebDriver.for :firefox
If you prefer not to set geckodriver's location using PATH, set the geckodriver binary location programmatically:
System.setProperty("webdriver.gecko.driver", "/path/to/geckodriver");
It is also possible to set the property at run time:
mvn test -Dwebdriver.gecko.driver=/path/to/geckodriver
It is currently possible to revert to the older, more feature complete Firefox driver, by installing Firefox47.0.1 or 45 ESR and specifying a desired capability of marionette as false. Later releases of Firefox are no longer compatible.
Edge
Edge is Microsoft's newest browser, included with Windows 10 and Server 2016. Updates to Edge are bundled with major Windows updates, so you'll need to download a binary which matches the build number of your currently installed build of Windows. The Edge Developer site contains links to all the available binaries. Bugs against the EdgeDriver implementation can be raised with Microsoft. If you'd like to run tests against Edge, but aren't running Windows 10, Microsoft offer free VMs for testers on the Edge Developer site.
WebDriver driver = new EdgeDriver();
If Edge driver is not present in your path, you can set the path using the following line:
System.setProperty("webdriver.edge.driver", "/path/to/edgedriver");
Internet Explorer
Internet Explorer was Microsoft's default browser until Windows 10, although it is still included in Windows 10. Internet Explorer Driver is the only driver The Selenium project aims to support the same releases Microsoft considers current. Older releases may work, but will be unsupported.
While the Selenium project provides binaries for both the 32-bit and 64-bit versions of Internet Explorer, there are some limitations with Internet Explorer 10 & 11 with the 64-bit driver, but using the 32-bit driver continues to work well. It should be noted that as Internet Explorer preferences are saved against the logged in user's account, some additional setup is required.
WebDriver driver = new InternetExplorerDriver();
If Internet Explorer driver is not present in your path, you can set the path using the following line:
System.setProperty("webdriver.ie.driver", "/path/to/iedriver");
Microsoft also offer a WebDriver binary for Internet Explorer 11 on Windows 7 & 8.1. It has not been updated since 2014 and is based of a draft version of the W3 specification. Jim Evans has an excellent writeup on Microsoft's implementation.
Opera
Current releases of Opera are built on top of the Chromium engine, and WebDriver is now supported via the closed-source Opera Chromium Driver, which can be added to your PATH or as a system property.
Instantiating a driver session is similar to Firefox and Chromium:
WebDriver driver = new OperaDriver();
require "selenium-webdriver" driver = Selenium::WebDriver.for :opera
Safari
Starting with Safari 10 on macOS El Capitan and Sierra, WebDriver support is included with each release of the browser. To enable support:
- Enable the Developer menu from Safari preferences
- Check the Allow Remote Automation option from with the Develop menu
- Run
/usr/bin/safaridriver -p 1337
from the terminal for the first time and type your password at the prompt to authorise WebDriver
You can then start a driver session using:
WebDriver driver = new SafariDriver();
Those looking to automate Safari on iOS should look to the Appium project. Whilst Safari was previously available for Windows, Apple has long since dropped support, making it a poor choice of test platform.
Mock browsers
HtmlUnit
HtmlUnit is a "GUI-Less browser for Java programs". It models HTML documents and provides an API that allows you to invoke pages, fill out forms, click links, etc. It has JavaScript support and is able to work with AJAX libraries, simulating Chrome, Firefox or Internet Explorer depending on the configuration used. It has been moved to a new location.
The source is maintained on svn.
PhantomJS
PhantomJS is a headless browser based on Webkit, albeit a version much older than that used by Google Chrome or Safari. . Whilst historically a popular choice, it would now be wise to avoid PhantomJS. The project has been unmaintained since the 5th of August, so whilst the web will continue to change, PhantomJS will not be updated. This was after Google announced the ability to run Chrome headlessly, something also now offered by Mozilla's Firefox.
BROWSER LAUNCHING AND MANIPULATION
Ruby
Ruby is not installed by default on Windows. Download the latest version and run the installer. You can leave all settings at default values, except at the Installation Destination and Optional Tasks screen check Add Ruby executables to your PATH checkbox. To drive any browser, you have to install selenium-webdriver Ruby gem. To install it, open command prompt and type this:
$ gem install selenium-webdriver
Internet Explorer
Internet Explorer is installed by default on Windows, so no installation is needed. To drive Internet Explorer on Windows, you have to download the latest Internet Explorer Driver and put the file into a folder that is in PATH. To find out which directories are in PATH, type echo %PATH% in command prompt.
$ echo %PATH% C:\Ruby200\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem
C:\Ruby200\bin looks like a good place. Unzip `IEDriverServer` file and move `IEDriverServer.exe` there. This should open a new Internet Explorer window:
System.setProperty("webdriver.ie.driver", /path/to/internetexplorerdriver); WebDriver driver = new InternetExplorerDriver();
require "selenium-webdriver" driver = Selenium::WebDriver.for :internet_explorer
WAITS
WebDriver can generally be said to have a blocking API. Because it is an out-of-process library thatinstructs the browser what to do, and because the web platform has an intrinsically asynchronous nature, WebDriver doesn't track the active, real-time state of the DOM. This comes with some challenges that we will discuss here.
From experience, most intermittents that arise from use of Selenium and WebDriver are connected to race conditions that occur between the browser and the user's instructions. An example could be that the user instructs the browser to navigate to a page, then gets a no such element error when trying to find an element.
Consider the following document:
<!doctype html> <meta charset=utf-8> <title>Race Condition Example<title> <script> var initialised = false; window.addEventListener("load", function() { var newElement = document.createElement("p"); newElement.textContent = "Hello from JavaScript!"; document.body.appendChild(newElement); initialised = true; }); </script>
The WebDriver instructions might look innocent enough:
driver.navigate("file:///race_condition.html") el = driver.find_element_by_tag_name("p") assert el.text == "Hello from JavaScript!"
The issue here is that the default page load strategy used in WebDriver listens for the document.readyState to change to "complete" before returning from the call to navigate. Because the p element is added after the document has completed loading, this WebDriver script might be intermittent. It “might” be intermittent because no guarantees can be made about elements or events that trigger asynchronously without explicitly waiting—or blocking—on those events.
Fortunately, using the normal instruction set available on the WebElement interface—such as WebElement.click and WebElement.sendKeys—are guaranteed to be synchronous, in that the function calls won't return (or the callback won't trigger in callback-style languages) until the command has been completed in the browser. The advanced user interaction APIs, Keyboard and Mouse, are exceptions as they are explicitly intended as “do what I say” asynchronous commands.
Waiting is having the automated task execution elapse a certain amount of time before continuing with the next step.
To overcome the problem of race conditions between the browser and your WebDriver script, most Selenium clients ship with a wait package. When employing a wait, you are using what is commonly referred to as an explicit wait.
Explicit waiting
Explicit waits are available to Selenium clients for imperative, procedural languages. They allow your code to halt program execution, or freeze the thread, until the condition you pass it resolves. The condition is called with a certain frequency until the timeout of the wait is elapsed. This means that for as long as the condition returns a falsy value, it will keep trying and waiting.
Since explicit waits allow you to wait for a condition to occur, they make a good fit for synchronising the state between the browser and its DOM, and your WebDriver script.
To remedy our buggy instruction set from earlier, we could employ a wait to have the findElement call wait until the dynamically added element from the script has been added to the DOM:
from selenium.webdriver.support.ui import WebDriverWait def document_initialised(driver): return driver.execute_script("return initialised") driver.navigate("file:///race_condition.html") WebDriverWait(driver).until(document_initialised) el = driver.find_element_by_tag_name("p") assert el.text == "Hello from JavaScript!"
We pass in the condition as a function reference that the wait will run repeatedly until its return value is truthy. A “truthful” return value is anything that evaluates to boolean true in the language at hand, such as a string, number, a boolean, an object (including a WebElement), or a populated (non-empty) sequence or list. That means an empty list evaluates to false. When the condition is truthful and the blocking wait is aborted, the return value from the condition becomes the return value of the wait.
With this knowledge, and because the wait utility ignores no such element errors by default, we can refactor our instructions to be more concise:
from selenium.webdriver.support.ui import WebDriverWait driver.navigate("file:///race_condition.html") el = WebDriverWait(driver).until(lambda d: return d.find_element_by_tag_name("p")) assert el.text == "Hello from JavaScript!"
In that example, we pass in an anonymous function (but we could also define it explicitly as we did earlier so it may be reused). The first and only argument that is passed to our condition is always a reference to our driver object, WebDriver (called d in the example). In a multi-threaded environment, you should be careful to operate on the driver reference passed in to the condition rather than the reference to the driver in the outer scope.
Because the wait will swallow no such element errors that are raised when the element isn't found, the condition will retry until the element is found. Then it will take the return value, a WebElement, and pass it back through to our script.
If the condition fails, e.g. a truthful return value from the condition is never reached, the wait will throw/raise an error/exception called a timeout error.
Options
The wait condition can be customised to match your needs. Sometimes it's unnecessary to wait the full extent of the default timeout, as the penalty for not hitting a successful condition can be expensive.
The wait lets you pass in an argument to override the timeout:
WebDriverWait(driver, timeout=3).until(some_condition)
Expected conditions
Because it's quite a common occurrence to have to synchronise the DOM and your instructions, most clients also come with a set of predefined expected conditions. As might be obvious by the name, they are conditions that are predefined for frequent wait operations.
The conditions available in the different language bindings vary, but this is a non-exhaustive list of a few:
alert is present
element exists
element is visible
title contains
title is
element staleness
visible text
You can refer to the API documentation for each client binding to find an exhaustive list of expected conditions:
Implicit waiting
There is a second type of wait that is distinct from explicit waits called implicit waiting. By implicitly waiting, WebDriver polls the DOM for a certain duration when trying to find any element. This can be useful when certain elements on the webpage are not available immediately and need some time to load.
Implicit waiting for elements to appear is disabled by default and will need to be manually enabled on a per-session basis. Mixing explicit waits and implicit waiting will cause unintended consequences, namely waits sleeping for the maximum time even if the element is available or condition is true.
Warning: Do not mix implicit and explicit waits. Doing so can cause unpredictable wait times. For example, setting an implicit wait of 10 seconds and an explicit wait of 15 seconds could cause a timeout to occur after 20 seconds.
An implicit wait is to tell WebDriver to poll the DOM for a certain amount of time when trying to find an element or elements if they are not immediately available. The default setting is 0, meaning disabled. Once set, the implicit wait is set for the life of the session.
WebDriver driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get("http://somedomain/url_that_delays_loading"); WebElement myDynamicElement = driver.findElement(By.id("myDynamicElement"));
FluentWait
FluentWait instance defines the maximum amount of time to wait for a condition, as well as the frequency with which to check the condition.
Users may configure the wait to ignore specific types of exceptions whilst waiting, such as NoSuchElementExceptions when searching for an element on the page.
// Waiting 30 seconds for an element to be present on the page, checking // for its presence once every 5 seconds. Wait<WebDriver> wait = new FluentWait<WebDriver>(driver) .withTimeout(30, SECONDS) .pollingEvery(5, SECONDS) .ignoring(NoSuchElementException.class); WebElement foo = wait.until(new Function<WebDriver, WebElement>() { public WebElement apply(WebDriver driver) { return driver.findElement(By.id("foo")); } });
FluentWait<By> fluentWait = new FluentWait<By>(By.tagName("TEXTAREA")); fluentWait.pollingEvery(100, TimeUnit.MILLISECONDS); fluentWait.withTimeout(1000, TimeUnit.MILLISECONDS); fluentWait.until(new Predicate<By>() { public boolean apply(By by) { try { return browser.findElement(by).isDisplayed(); } catch (NoSuchElementException ex) { return false; } } }); browser.findElement(By.tagName("TEXTAREA")).sendKeys("text to enter");
SUPPORT CLASSES
JAVASCRIPT ALERTS, PROMPTS AND CONFIRMATIONS
WebDriver provides an API for working with the three types of native popup message offered by JavaScript. These popups are styled by the browser and offer limited customisation.
Alerts
The simplest of these is referred to as an alert, which shows a custom message, and a single button which dismisses the alert, labelled in most browsers as OK. It can also be dismissed in most browsers by pressing the close button, but this will always do the same thing as the OK button. See an example alert.
WebDriver can get the text from the popup and accept or dismiss these alerts.
//Click the link to activate the alert driver.findElement(By.linkText("See an example alert")).click(); //Wait for the alert to be displayed and store it in a variable Alert alert = wait.until(ExpectedConditions.alertIsPresent()); //Store the alert text in a variable String text = alert.getText(); //Press the OK button alert.accept(); # Click the link to activate the alert driver.find_element_by_link_text("See an example alert").click() # Wait for the alert to be displayed and store it in a variable alert = wait.until(expected_conditions.alert_is_present()) # Store the alert text in a variable text = alert.text # Press the OK button alert.accept()
Confirm
A confirm box is similar to an alert, except the user can also choose to cancel the message. See a sample confirm.
This example also shows a different approach to storing an alert:
//Click the link to activate the alert driver.findElement(By.linkText("See a sample confirm")).click(); //Wait for the alert to be displayed wait.until(ExpectedConditions.alertIsPresent()); //Store the alert in a variable Alert alert = driver.switchTo().alert(); //Store the alert in a variable for reuse String text = alert.getText(); //Press the Cancel button alert.dismiss(); # Click the link to activate the alert driver.find_element_by_link_text("See a sample confirm").click() # Wait for the alert to be displayed wait.until(expected_conditions.alert_is_present()) # Store the alert in a variable for reuse alert = driver.switch_to.alert # Store the alert text in a variable text = alert.text # Press the Cancel button alert.dismiss()
Prompt
Prompts are similar to confirm boxes, except they also include a text input. Similar to working with form elements, you can use WebDriver's send keys to fill in a response. This will completely replace the placeholder text. Pressing the cancel button will not submit any text. See a sample prompt.
//Click the link to activate the alert driver.findElement(By.linkText("See a sample prompt")).click(); //Wait for the alert to be displayed and store it in a variable Alert alert = wait.until(ExpectedConditions.alertIsPresent()); //Type your message alert.sendKeys("Selenium"); //Press the OK button alert.accept(); # Click the link to activate the alert driver.find_element_by_link_text("See a sample prompt").click() # Wait for the alert to be displayed wait.until(expected_conditions.alert_is_present()) # Store the alert in a variable for reuse alert = Alert(driver) # Type your message alert.send_keys("Selenium") # Press the OK button alert.accept()
HTTP PROXIES
PAGE LOADING STRATEGY
WEB ELEMENTS
KEYBOARD
MOUSE
WEBDRIVER
Selenium最近的最大变化是包含了WebDriver API。以本地方式做为用户驱动浏览器将在本地或使用Selenium服务器的远程计算机上运行,这标志着浏览器自动化方面的一次飞跃。
Selenium WebDriver与RC的做用相同,而且包含原始的1.x绑定。它涉及语言绑定和各个浏览器控制代码的实现。这一般被称为WebDriver 或有时被称为Selenium 2。
Selenium 1.0 + WebDriver = Selenium 2.0
- WebDriver的设计更简单,更简洁的编程界面,同时解决了Selenium-RC API中的一些限制。
- 与Selenium 1.0相比,WebDriver是一个紧凑的面向对象API。
- 它更有效地驱动浏览器,并克服了Selenium 1的局限性,这些限制影响了咱们的功能测试覆盖范围,如文件上传或下载,弹出窗口和对话框屏障。
- WebDriver克服了Selenium RC的单主机起源策略的局限性 。
驱动要求
经过WebDriver,Selenium支持市场上全部主流浏览器,如Chrom(ium),Firefox,Internet Explorer,Opera和Safari。在可能的状况下,WebDriver使用浏览器对自动化的内置支持来驱动浏览器,但并不是全部浏览器都支持远程控制。
WebDriver的目标是尽量模仿真实用户与浏览器的交互。在不一样的浏览器中,这是可能的。有关不一样驱动程序特性的更多详细信息,请参阅驱动程序特性。
即便全部驱动程序共享一个用于控制浏览器的面向用户的界面,但它们在设置浏览器会话方面略有不一样。因为许多驱动程序实现由第三方提供,所以它们不包含在标准的Selenium发行版中。
驱动程序实例化,配置文件管理以及各类浏览器特定设置是根据浏览器具备不一样要求的参数示例。本节介绍让您开始使用不一样浏览器的基本要求。
将可执行文件添加到您的PATH
大多数驱动程序须要一个额外的可执行文件让Selenium与浏览器通讯。您能够在启动WebDriver以前手动指定可执行文件的位置,但这可能会使测试的可移植性下降,由于可执行文件须要位于每台计算机的相同位置,或者包含在测试代码库中。
经过将包含WebDriver二进制文件的文件夹添加到系统路径中,Selenium将可以找到其余二进制文件,而无需您的测试代码来查找驱动程序的确切位置。
- 建立一个目录来放置浏览器驱动可执行文件,例如 C:\ WebDriver \ bin或/ opt / WebDriver / bin
- 将该目录添加到系统环境变量PATH中:
- 在Windows上 - 以管理员身份打开命令提示符,而后运行如下命令将该目录永久地添加到您计算机上全部用户的路径中:
setx /m path “%path%;C:\WebDriver \bin\”
- 在macOS和Linux上使用bash用户 - 在终端中:
export PATH=$PATH:/opt/WebDriver/bin >> 〜/.profile
- 您如今能够验证您的更改是否有效。关闭全部打开的命令提示符并打开一个新提示符。在上一步建立的文件夹中输入其中一个二进制文件的名称,例如:
chromedriver
。若是您的PATH配置正确,您会看到一些与驱动程序启动有关的输出:
Starting ChromeDriver 2.25.426935 (820a95b0b81d33e42712f9198c215f703412e1a1) on port 9515 Only local connections are allowed.
按下,您能够从新得到对命令提示符的控制Ctrl + C。
快速参考
浏览器
|
支持的OS
|
由...维护
|
下载
|
问题跟踪器
|
铬/铬
|
Windows
macOS
Linux
|
谷歌
|
|
|
火狐
|
Windows
macOS
Linux
|
Mozilla
|
|
|
边缘
|
Windows 10
|
微软
|
|
|
IE浏览器
|
视窗
|
硒项目
|
|
|
苹果浏览器
|
macOS El Capitan和更新的
|
苹果
|
内置
|
|
歌剧
|
Windows
macOS
Linux
|
歌剧
|
|
|
铬/铬
在Linux或macOS上,这意味着修改PATH环境变量。您能够经过执行如下命令来查看以冒号分隔的目录是否构成系统的路径:
$ echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
若是路径中还没有包含chromedriver,请确保包含chromedriver二进制文件的父目录。如下行将设置PATH环境变量的当前内容,并在冒号后添加一个额外的路径:
$ export PATH="$PATH:/path/to/chromedriver"
当您的路径上有可用的chromedriver时,您应该可以从任何目录执行_chromedriver_可执行文件。
要实例化Chrome / Chromium会话,您能够执行如下操做:
WebDriver driver = new ChromeDriver();
请记住,您必须将路径设置为chromedriver可执行文件。这可使用如下行:
System.setProperty("webdriver.chrome.driver", "/path/to/chromedriver");
require "selenium-webdriver" driver = Selenium::WebDriver.for :chrome
chromedriver被看成WebDriver远程服务器,它经过公开chrome的内部自动代理接口来指挥浏览器作什么
火狐
从Selenium 3开始,Mozilla利用geckodriver接管了Firefox Driver的实现。Firefox的新驱动称为geckodriver,适用于Firefox 48及更新版本。因为Firefox WebDriver正在开发中,Firefox版本越新越好。
因为geckodriver是启动Firefox的新默认方式,所以您能够像Selenium 2同样实例化Firefox:
WebDriver driver = new FirefoxDriver();
require "selenium-webdriver" driver = Selenium::WebDriver.for :firefox
若是您不想使用PATH设置geckodriver的位置,请以编程方式设置geckodriver二进制位置:
System.setProperty("webdriver.gecko.driver", "/path/to/geckodriver");
也能够在运行时设置属性:
mvn test -Dwebdriver.gecko.driver=/path/to/geckodriver
目前有可能经过安装Firefox 47.0.1 或45 ESR 并将所需的木偶功能指定为 false来恢复到较老的,功能更完整的Firefox驱动程序 。Firefox的后续版本再也不兼容。
Edge
Edge是Microsoft最新的浏览器,包含在Windows 10和Server 2016中。Edge的更新与主要Windows更新捆绑在一块儿,所以您须要下载与您当前安装的Windows版本号相匹配的二进制文件。该边缘开发人员网站 包含指向全部可用的二进制文件。微软能够提出针对EdgeDriver实施的错误 。若是您但愿针对Edge运行测试,但不运行Windows 10,Microsoft会在Edge开发人员网站上为测试人员提供免费虚拟机。
WebDriver driver = new EdgeDriver();
若是Edge驱动程序不在您的路径中,则可使用如下行设置路径:
System.setProperty("webdriver.edge.driver", "/path/to/edgedriver");
IE浏览器
在Windows 10以前,Internet Explorer是微软的默认浏览器,尽管它仍然包含在Windows 10中。Internet Explorer驱动程序是惟一的驱动程序Selenium项目旨在支持 Microsoft认为的最新版本 。旧版本可能有效,但不受支持。
虽然Selenium项目为32位和64位版本的Internet Explorer提供了二进制文件,但Internet Explorer 10和11在64位驱动程序方面存在一些局限性,但使用32位驱动程序仍能正常运行。应该注意的是,因为Internet Explorer首选项是针对登陆用户的账户保存的,所以须要进行一些额外的设置。
WebDriver driver = new InternetExplorerDriver();
若是Internet Explorer驱动程序不在您的路径中,则可使用如下行来设置路径:
System.setProperty("webdriver.ie.driver", "/path/to/iedriver");
Opera
实例化驱动程序会话与Firefox和Chromium相似:
WebDriver driver = new OperaDriver();
require "selenium-webdriver" driver = Selenium::WebDriver.for :opera
Safari
从macOS El Capitan和Sierra上的Safari 10开始,每一个浏览器版本都包含WebDriver支持。启用支持:
- 从Safari偏好设置启用开发者菜单
- 使用“显影”菜单检查“ 容许远程自动化”选项
- 跑
/ usr / bin / safaridriver -p 1337
从终端第一次,并在提示输入您的密码受权WebDriver
而后可使用如下命令启动驱动程序会话
WebDriver driver = new SafariDriver();
那些但愿在iOS上自动化Safari的人应该看看 Appium项目。虽然之前Safari可用于Windows,但Apple早已再也不维护,使其成为测试平台的糟糕选择。
模拟浏览器
HtmlUnit
HtmlUnit是一个“Java程序的无GUI浏览器”。它模拟HTML文档,并提供一个API,使您能够调用页面,填写表单,单击连接等。它支持JavaScript,可使用AJAX库,根据所用配置模拟Chrome,Firefox或Internet Explorer。它已被移到一个 新的位置。
源代码保存在svn上。
PhantomJS
PhantomJS是一款基于Webkit的无头浏览器,尽管它的版本比Google Chrome或Safari使用的版本要早得多。。虽然历史上流行的选择,但避免PhantomJS如今是明智的。该项目自8月5日以来一直未获得维护 ,所以虽然网络将继续发生变化,但PhantomJS不会更新。这是在谷歌宣布无线运行Chrome的能力以后,如今Mozilla的Firefox也提供了一些功能。
浏览器启动和操做
Ruby
在Windows上默认不安装Ruby。下载最新版本并运行安装程序。您能够将全部设置保留为默认值,除了在“ 安装目标”和“可选任务”屏幕中检查将Ruby可执行文件添加到PATH复选框。要驱动任何浏览器,您必须安装selenium-webdriver Ruby gem。要安装它,请打开命令提示符并输入:
$ gem install selenium-webdriver
IE浏览器
Internet Explorer默认安装在Windows上,所以不须要安装。要在Windows上驱动Internet Explorer,必须下载最新的Internet Explorer驱动程序,并将该文件放入PATH中的文件夹中。要找出PATH中的哪些目录,请在命令提示符下键入echo%PATH%。
$ echo %PATH% C:\Ruby200\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem
C:\ Ruby200 \ bin看起来像个好地方。解压缩`IEDriverServer`文件并将`IEDriverServer.exe`移动到那里。这应该打开一个新的Internet Explorer窗口:
System.setProperty("webdriver.ie.driver", /path/to/internetexplorerdriver); WebDriver driver = new InternetExplorerDriver();
require "selenium-webdriver" driver = Selenium::WebDriver.for :internet_explorer
WAITS功能
一般能够说WebDriver具备阻塞API。因为它是一个进程外库,它 指示浏览器执行什么操做,而且由于Web平台具备内在的异步特性,因此WebDriver不会跟踪DOM的活动实时状态。这带来了一些挑战,咱们将在这里讨论。。
根据经验,使用Selenium和WebDriver产生的大部分间歇性事件都与浏览器和用户指令之间出现的争用条件相关联。一个例子多是用户指示浏览器导航到页面,而后在尝试查找元素时没有发现此类元素错误。
参考如下文件:
<!doctype html> <meta charset=utf-8> <title>Race Condition Example<title> <script> var initialised = false; window.addEventListener("load", function() { var newElement = document.createElement("p"); newElement.textContent = "Hello from JavaScript!"; document.body.appendChild(newElement); initialised = true; }); </script>
WebDriver指令可能看起来无辜:
driver.navigate("file:///race_condition.html") el = driver.find_element_by_tag_name("p") assert el.text == "Hello from JavaScript!"
这里的问题是WebDriver中使用的默认页面加载策略监听文档。readyState更改成“complete”,而后从调用返回导航。由于p元素是在文档完成加载以后添加的,因此这个WebDriver脚本多是间歇性的。它“可能”是间歇性的,由于不能对异步触发的元素或事件做出保证,而不须要显式地等待或阻塞这些事件。
幸运的是,使用WebElement接口上可用的普通指令集(例如WebElement.click和WebElement.sendKeys)保证是同步的,由于函数调用不会返回(或者回调将不会以回调式触发语言),直到浏览器中的命令完成。高级用户交互API 键盘和 鼠标是例外,由于它们显式地用做“按我说的作”异步命令。
在继续下一步以前,等待会让自动任务执行过去一段时间。
为了克服浏览器和WebDriver脚本之间的竞争情况问题,大多数Selenium客户端都附带一个等待包。当采用等待时,您正在使用一般被称为显式等待的内容。
显式等待
Selenium客户端可使用显式等待来使用命令式的过程语言。它们容许您的代码中止程序执行,或者冻结线程,直到您经过的条件获得解决。以特定频率调用条件,直到等待超时。这意味着只要条件返回一个虚假值,它就会继续尝试和等待。
因为显式等待容许您等待条件发生,所以它们很是适合于同步浏览器及其DOM和WebDriver脚本之间的状态。
为了补救咱们早期的错误指令集,咱们能够等待findElement调用等待,直到脚本中动态添加的元素被添加到DOM:
from selenium.webdriver.support.ui import WebDriverWait def document_initialised(driver): return driver.execute_script("return initialised") driver.navigate("file:///race_condition.html") WebDriverWait(driver).until(document_initialised) el = driver.find_element_by_tag_name("p") assert el.text == "Hello from JavaScript!"
咱们将条件做为函数引用传递,等待将重复运行,直到其返回值为真。一个“真实的”返回值是任何在手头语言中评估为boolean true的东西,如字符串,数字,布尔值,对象(包括WebElement)或填充(非空)序列或列表。这意味着一个空列表的计算结果为false。当条件是真实的而且阻塞等待被停止时,来自条件的返回值变成等待的返回值。
有了这些知识,而且因为等待实用程序默认状况下不会忽略此类元素错误,因此咱们能够将咱们的指示重构得更加简洁:
from selenium.webdriver.support.ui import WebDriverWait driver.navigate("file:///race_condition.html") el = WebDriverWait(driver).until(lambda d: return d.find_element_by_tag_name("p")) assert el.text == "Hello from JavaScript!"
在这个例子中,咱们传入一个匿名函数(但咱们也能够像前面那样明确地定义它,以便它能够被重用)。传递给咱们的条件的第一个也是惟一的参数始终是对咱们的驱动程序对象WebDriver (在该示例中称为d)的引用。在多线程环境中,您应该当心地对传入条件的驱动程序引用进行操做,而不是在外部范围中对驱动程序的引用。
由于等待将不会消除元素未找到时引起的此类元素错误,则条件将重试,直到找到该元素。而后它将得到返回值,一个WebElement,并将其传回给咱们的脚本。
若是条件失败,例如从条件获得的真实返回值永远不会达到,那么等待将抛出/引起称为超时错误的错误/异常。
选项
等待条件能够定制以知足您的需求。有时没有必要等待默认超时的所有范围,由于没有达到成功条件的代价会很昂贵。
等待让你传入一个参数来覆盖超时:
WebDriverWait(driver, timeout=3).until(some_condition)
预期条件
由于必须同步DOM和您的指令是很常见的事情,因此大多数客户还会附带一组预约义的预期条件。由名称可能很明显,它们是为频繁等待操做而预约义的条件。
不一样语言绑定中可用的条件各不相同,但这是一个非穷举的列表:
警报存在
元素存在
元素是可见的
标题包含
标题是
元素陈旧
可见的文本
您能够参考每一个客户端绑定的API文档以查找预期条件的详尽列表:
隐含的等待
还有第二种类型的等待与显式等待不一样, 称为隐式等待。经过隐式等待,WebDriver在尝试查找任何元素时轮询DOM一段时间。当网页上的某些元素不可当即使用并须要一些时间加载时,这可能颇有用。
默认状况下隐式等待元素出现,而且须要在每一个会话的基础上手动启用。混合明确的等待和隐含的等待将致使意想不到的后果,即等待最大时间睡眠,即便元素可用或条件为真。
警告: 不要混合隐式和显式等待。这样作会致使没法预测的等待时间。例如,设置10秒的隐式等待和15秒的明确等待可能会致使20秒后发生超时。
隐含的等待是告诉WebDriver在尝试查找一个或多个元素(若是它们不是当即可用的)时轮询DOM一段时间。默认设置为0,意味着禁用。一旦设置,隐含的等待就设置为会话的整个生命周期。
WebDriver driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get("http://somedomain/url_that_delays_loading"); WebElement myDynamicElement = driver.findElement(By.id("myDynamicElement"));
FluentWait
FluentWait实例定义了等待条件的最长时间以及检查条件的频率。
用户能够配置等待,以在等待时忽略特定类型的异常,例如NoSuchElementException在页面上搜索元素时。
// Waiting 30 seconds for an element to be present on the page, checking // for its presence once every 5 seconds. Wait<WebDriver> wait = new FluentWait<WebDriver>(driver) .withTimeout(30, SECONDS) .pollingEvery(5, SECONDS) .ignoring(NoSuchElementException.class); WebElement foo = wait.until(new Function<WebDriver, WebElement>() { public WebElement apply(WebDriver driver) { return driver.findElement(By.id("foo")); } });
FluentWait<By> fluentWait = new FluentWait<By>(By.tagName("TEXTAREA")); fluentWait.pollingEvery(100, TimeUnit.MILLISECONDS); fluentWait.withTimeout(1000, TimeUnit.MILLISECONDS); fluentWait.until(new Predicate<By>() { public boolean apply(By by) { try { return browser.findElement(by).isDisplayed(); } catch (NoSuchElementException ex) { return false; } } }); browser.findElement(By.tagName("TEXTAREA")).sendKeys("text to enter");
支持类
JAVASCRIPT警报,提示和确认
WebDriver提供了一个用于处理JavaScript提供的三种本地弹出消息的API。这些弹出窗口由浏览器设置并提供有限的自定义。
Alerts
其中最简单的就是一个警报,它显示了一个自定义消息,以及一个按钮,它解除了警报,在大多数浏览器中标记为OK。它也能够经过按下关闭按钮在大多数浏览器中被解散,可是这老是和OK按钮同样。查看示例警报。
WebDriver能够从弹出窗口中获取文本并接受或拒绝这些警报。
//Click the link to activate the alert driver.findElement(By.linkText("See an example alert")).click(); //Wait for the alert to be displayed and store it in a variable Alert alert = wait.until(ExpectedConditions.alertIsPresent()); //Store the alert text in a variable String text = alert.getText(); //Press the OK button alert.accept(); # Click the link to activate the alert driver.find_element_by_link_text("See an example alert").click() # Wait for the alert to be displayed and store it in a variable alert = wait.until(expected_conditions.alert_is_present()) # Store the alert text in a variable text = alert.text # Press the OK button alert.accept()
Confirm
确认框与提示相似,除了用户也能够选择取消消息。查看样本确认。
此示例还显示了一种用于存储警报的不一样方法:
//Click the link to activate the alert driver.findElement(By.linkText("See a sample confirm")).click(); //Wait for the alert to be displayed wait.until(ExpectedConditions.alertIsPresent()); //Store the alert in a variable Alert alert = driver.switchTo().alert(); //Store the alert in a variable for reuse String text = alert.getText(); //Press the Cancel button alert.dismiss(); # Click the link to activate the alert driver.find_element_by_link_text("See a sample confirm").click() # Wait for the alert to be displayed wait.until(expected_conditions.alert_is_present()) # Store the alert in a variable for reuse alert = driver.switch_to.alert # Store the alert text in a variable text = alert.text # Press the Cancel button alert.dismiss()
Prompt
提示与确认框类似,除了它们还包含文本输入。与使用表单元素相似,您可使用WebDriver的发送键来填写响应。这将彻底取代占位符文本。按取消按钮不会提交任何文本。 查看示例提示。
//Click the link to activate the alert driver.findElement(By.linkText("See a sample prompt")).click(); //Wait for the alert to be displayed and store it in a variable Alert alert = wait.until(ExpectedConditions.alertIsPresent()); //Type your message alert.sendKeys("Selenium"); //Press the OK button alert.accept(); # Click the link to activate the alert driver.find_element_by_link_text("See a sample prompt").click() # Wait for the alert to be displayed wait.until(expected_conditions.alert_is_present()) # Store the alert in a variable for reuse alert = Alert(driver) # Type your message alert.send_keys("Selenium") # Press the OK button alert.accept()
HTTP代理
页面加载策略
WEB元素
键盘
鼠标