Selenium 2.0最主要的新特性就是集成了WebDriver API。咱們設計WebDriver的初衷是提供更加簡單明瞭的接口來彌補Selenium-RC API的不足。在動態網頁中,一般只會更新局部的html元素,WebDriver會很好的幫助用戶快速定位這些元素。咱們最終的目的是經過提供精心設計的面向對象API來解決現代高級網頁中的測試難題。javascript
不一樣類型的瀏覽器都會有原生的接口支持自動化操做,Selenium經過這些接口直接向瀏覽器發送指令。如何發送這些指令取決於你當前使用的瀏覽器類型,咱們將在這一章節後面來詳細介紹。css
看上去WebDriver與以前Selenium-RC的實現方式相似,實際上二者之間存在着本質的區別。對於全部類型的瀏覽器Selenium-RC都是使用的同一種方法:當瀏覽器啓動時,向其中注入javascript,從而使用這些js來驅動瀏覽器中的AUT(Application Under Test)。WebDriver並無使用這種技術,它是經過調用瀏覽器原生的自動化API直接驅動瀏覽器。html
是否須要是用Selenium Server取決於你使用WebDriver的方式。如下兩種狀況不須要使用Selenium Server,WebDriver直接運行瀏覽器便可:一、testcases僅僅使用了Webdriver的API;二、瀏覽器和testcase在同一臺PC上,並且testcases僅僅使用了Webdriver的API。前端
如下三種狀況你須要結合Selenium Server來使用WebDriver:java
1)使用Selenium-Grid管理集羣環境(或者虛擬機)上的testcase;python
2)須要調用非本機上的不一樣版本的瀏覽器;web
3)未使用任何language binding(java/c#/python/ruby),且有意向使用HtmlUnitDriver。apache
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>MySel20Proj</groupId> <artifactId>MySel20Proj</artifactId> <version>1.0</version> <dependencies> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>2.38.0</version> </dependency> <dependency> <groupId>com.opera</groupId> <artifactId>operadriver</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>com.opera</groupId> <artifactId>operadriver</artifactId> <version>1.5</version> <exclusions> <exclusion> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-remote-driver</artifactId> </exclusion> </exclusions> </dependency> </dependencies> </dependencyManagement> </project>請確認你使用的WebDriver是最新的當前版本。在這篇文檔撰寫時,上述示例給出的是最新的版本。在Selenium2.0發佈不久WebDriver就有過頻繁的更新。請在這個連接 Maven Download Page確認當前的版本,相應地修改你工程中的pon.xml。
如今,你能夠經過dos界面使用CD命令進入工程所在文件夾,經過如下命令運行Maven。編程
mvn clean install
運行以後會自動下載Selenium及相關套件,並加載到你的工程中去。c#
最後,將你的工程導入到你偏好的IDE中。若是你對導入的過程不是很清楚,咱們已經準備了操做指南。
Importing a maven project into IntelliJ IDEA.Importing a maven project into Eclipse
已經在Selenium1.0上構建測試工程的用戶,咱們爲您提供了一份指導如何將已有的代碼遷移到Selenium2.0。Selenium2.0的首席開發工程師Simon Stewart爲此撰寫了一片文章:Magrating From Selenium RC to Selenium WebDriver。
如今你確定躍躍欲試要寫一些代碼了。咱們以一個簡單的例子來開始第一段旅程:在Google上搜索「Cheese」,並打印出搜索結果網頁的標題。
package org.openqa.selenium.example; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.support.ui.ExpectedCondition; import org.openqa.selenium.support.ui.WebDriverWait; public class Selenium2Example { public static void main(String[] args) { // 建立一個FirefoxDriver實例 // 這個類依賴於接口而不是接口的實現 WebDriver driver = new FirefoxDriver(); // 使用get方法訪問Google driver.get("http://www.google.com"); // 使用下面這個方法也可以達到訪問Google的目的 // driver.navigate().to("http://www.google.com"); // 找到html輸入框的name WebElement element = driver.findElement(By.name("q")); // 輸入要查找的內容 element.sendKeys("Cheese!"); // 提交表單,WebDriver會自動找到咱們須要提交的元素所在的表單 element.submit(); // 打印網頁的標題 System.out.println("Page title is: " + driver.getTitle()); // Google的搜索網頁會經過JS動態渲染 // 等待頁面加載完畢,超時時間爲10秒 (new WebDriverWait(driver, 10)).until(new ExpectedCondition<Boolean>() { public Boolean apply(WebDriver d) { return d.getTitle().toLowerCase().startsWith("cheese!"); } }); // 控制檯上將打印以下信息: "cheese! - Google Search" System.out.println("Page title is: " + driver.getTitle()); // 關閉瀏覽器 driver.quit(); } }
在本章節的接下來篇幅,咱們將學習如何使用WebDriver操做你的瀏覽器,如何使用框架和窗口來測試Web網站。固然,咱們將提供更加翔實的論述和舉例。
driver.get("http://www.google.com");在某些狀況下,好比操做系統和瀏覽器的穿插組合,WebDriver有可能不會等待Web頁面加載完成,這種狀況下WebDriver會返回錯誤或者直接運行下一步操做。爲了保證程序的健壯性,你須要等待頁面中某個元素加載完成後再進行下一步操做,請參考 Explicit and Implicit Waits。
<div id="coolestWidgetEvah">...</div> WebElement element = driver.findElement(By.id("coolestWidgetEvah"));
By Class Name
在這種場景下,咱們引用DOM元素的屬性。實際狀況是不少元素都有同樣的Class Name,所以找到多個有相同Class Name的元素,比找到第一個擁有這個Class Name的元素來的更重要。
示例:如何使用該方法定位元素
<div class="cheese"><span>Cheddar</span></div><div class="cheese"><span>Gouda</span></div> List<WebElement> cheeses = driver.findElements(By.className("cheese"));
DOM元素Tag的名稱。
示例:如何使用該方法定位元素
<iframe src="..."></iframe> WebElement frame = driver.findElement(By.tagName("iframe"));
找到與Name屬性相同的Input元素。
示例:如何使用該方法定位元素
<input name="cheese" type="text"/> WebElement cheese = driver.findElement(By.name("cheese"));
找到與Text屬性精確匹配的超連接。
示例:如何使用該方法定位元素
<a href="http://www.google.com/search?q=cheese">cheese</a> WebElement cheese = driver.findElement(By.linkText("cheese"));
找到與Text屬性模糊匹配的超連接。
示例:如何使用該方法定位元素<a href="http://www.google.com/search?q=cheese">search for cheese</a> WebElement cheese = driver.findElement(By.partialLinkText("cheese"));
示例:如何使用該方法定位元素
<div id="food"><span class="dairy">milk</span><span class="dairy aged">cheese</span></div> WebElement cheese = driver.findElement(By.cssSelector("#food span.dairy.aged"));
By XPath
當有須要時,WebDriver還可使用瀏覽器自帶的XPATH。對於那些不支持XPATH的瀏覽器,咱們提供了WebDriver特有的實現方式。請確保熟悉XPATH在不一樣的引擎中的區別,不然會致使一些不可預料的問題。
Driver | 大小寫敏感 | 屬性值是否可見 | 是否支持XAPTH |
HtmlUnit Driver | 僅識別小寫 | 可見 | 是 |
IE Driver | 僅識別小寫 | 可見 | 否 |
FireFox Diver | 大小寫不敏感 | 可見 | 是 |
上面的表格有一些抽象,讓咱們來看個例子
<input type="text" name="example" /> <INPUT type="text" name="other" /> List<WebElement> inputs = driver.findElements(By.xpath("//input"));
匹配結果以下
XPATH表達式 | HtmlUnit Driver | FireFox Driver | IE Driver |
//input | 1 | 2 | 2 |
//INPUT | 0 | 2 | 0 |
有些標籤的屬性有默認值,這種狀況下不指定屬性值則匹配默認值。好比,"input"標籤"type"屬性默認爲"text"。使用XPATH的首要原則就是不要忽略這些隱藏的實現。
使用JavaScript
只要返回的是一個Web Element,你還可使用任意的JS代碼查找Web元素,根據查詢結果會自動修改成一個WebElement對象。
一個簡單的使用jQuery的例子:
WebElement element = (WebElement) ((JavascriptExecutor)driver).executeScript("return $('.cheese')[0]");
查找頁面中每一個label的全部Input元素:
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);
WebElement select = driver.findElement(By.tagName("select")); List<WebElement> allOptions = select.findElements(By.tagName("option")); for (WebElement option : allOptions) { System.out.println(String.format("Value is: %s", option.getAttribute("value"))); option.click(); }
Select select = new Select(driver.findElement(By.tagName("select"))); select.deselectAll(); select.selectByVisibleText("Edam");
driver.findElement(By.id("submit")).click();
element.submit();
driver.switchTo().window("windowName");
<a href="somewhere.html" target="windowName">Click here to open a new window</a>
for (String handle : driver.getWindowHandles()) { driver.switchTo().window(handle); }
driver.switchTo().frame("frameName");
driver.switchTo().frame("frameName.0.child");以上方法將切換到名稱爲「frameName」的Frame的第一個子Frame,全部Frame都是Web頁面的最頂端開始計數。
Alert alert = driver.switchTo().alert();
前文中,咱們使用get方法來獲取網頁(driver.get("http://www.example.com"))。正如你看到的,WebDriver有很多輕量級的功能聚焦的接口,Navigation就是這樣一個。正由於加載網頁是一個再普通不過的需求,這個方法存在於Driver類下面,可是用法很簡單:
driver.navigate().to("http://www.example.com");
重申一下,"navigate().to()"和"get()"作的是一樣的事情,只不過其中一個更適合打印。
Navigate接口還提供方法能夠在瀏覽器歷史記錄中先後翻頁。
driver.navigate().forward(); driver.navigate().back();
請注意,以上功能徹底取決於底層的瀏覽器。若是你習慣跨瀏覽器操做,當你使用這些接口時可能會出現意想不到的的異常。
// 打開Cookie做用的網站 driver.get("http://www.example.com"); // 設置全局Cookie Cookie cookie = new Cookie("key", "value"); driver.manage().addCookie(cookie); // 輸出當前網頁全部可用的Cookie Set<Cookie> allCookies = driver.manage().getCookies(); for (Cookie loadedCookie : allCookies) { System.out.println(String.format("%s -> %s", loadedCookie.getName(), loadedCookie.getValue())); } // 你又三種方法刪除Cookie // By name driver.manage().deleteCookieNamed("CookieName"); // By Cookie driver.manage().deleteCookie(loadedCookie); // Or all of them driver.manage().deleteAllCookies();
FirefoxProfile profile = new FirefoxProfile(); profile.addAdditionalPreference("general.useragent.override", "some UA string"); WebDriver driver = new FirefoxDriver(profile);
下面是一個拖拽Web頁面元素的例子,前提是本地事件必須可用。
WebElement element = driver.findElement(By.name("source")); WebElement target = driver.findElement(By.name("target")); (new Actions(driver)).dragAndDrop(element, target).perform();
譯者注:
一、原文連接:http://www.seleniumhq.org/docs/03_webdriver.jsp。
二、文中只包含了java相關的操做,WebDriver還支持c#/Python/Ruby/Perl/PHP/Perl,若有須要,請閱讀原文。
三、language binding,又叫glue code,意思是膠水代碼,好比有個C++的lib庫,java調用這個庫的api就叫java binding。參考:http://en.wikipedia.org/wiki/Language_binding。
四、措辭拙劣,有些單詞句子沒有深究就直譯了,深感從閱讀到翻譯差的不只僅是一本字典,還有文化的差別。筆者強烈推薦直接閱讀官網上的原文,若是個人譯文給你形成誤解,深感不安。這也是最後三章不敢繼續班門弄斧的緣由,等我對Selenium熟悉了以後再回來補全。