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元素
鍵盤
鼠標