Selenium2 WebDriver入門

1      簡介

資源

jar包:http://code.google.com/p/selenium/downloads/list or http://selenium-release.storage.googleapis.com/index.html 

官方 UserGuide:http://seleniumhq.org/docs/

2      基本配置

2.1      Firefox

對於不同的瀏覽器,需要創建不同類型的WebDriver進行測試,默認情況下我們通常可以直接 new XXXDriver() 來創建對應類型的 WebDriver。

如果使用Firefox測試,而Firefox又沒有安裝在默認目錄下,那麼直接 new FirefoxDriver()將會出現異常提示找不到瀏覽器。這時,我們需要在程序開始調用以下代碼,用以指定Firefox的位置:

System.setProperty(“webdriver.firefox.bin”, “***\\firefox.exe”)

或者我們使用 FirefoxBinary 實例來指定瀏覽器的位置:

File firefox = new File(“…\\firefox.exe”);

FirefoxBinary firefoxbin = new FirefoxBinary(firefox);

WebDriver driver = new FirefoxDriver(firefoxbin, null);

       值得注意的是,使用以上兩種配置啓動的Firefox瀏覽器是“全新”的,也就是說瀏覽器的設置都是初始的,包括插件集。這會使依賴 Firebug 等插件的開發調試工作無法進行,於是我們需要保留瀏覽器的配置信息。

這需要使用FirefoxProfile 實例來指定配置文件的位置:

                   String path = System.getProperty( "user.home" )

                                     + "\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\";

                   File prodir = new File( path );

                   File[] files = prodir.listFiles( new FilenameFilter()

                   {

                            @Override

                            public boolean accept( File dir, String name )

                            {

                                     return name.endsWith( ".default" );

                            }

                   } );

                   FirefoxProfile profile = new FirefoxProfile( files[0] );

       綜上而言,我們通常會使用 FirefoxDriver(FirefoxBinarybinary, FirefoxProfile profile) 形式的構造器。

 

2.2      Chrome

與Firefox類似,如果測試程序找不到Chrome的安裝位置(非默認位置),那麼可以這樣指定:

System.setProperty(“webdriver.chrome.driver”, “***\\chrome.exe”)

但是,使用Chrome測試,比較特別的是,需要驅動程序:

http://chromedriver.storage.googleapis.com/index.html

通常,我們使用 ChromeDriver(ChromeDriverServiceservice, ChromeOptions options) 形式的構造器,前一參數可指定驅動程序的位置,後一參數可指定瀏覽器的位置。

ChromeDriverService 實例的創建如下:

String chromeDriver = "…\\chromedriver.exe";

ChromeDriverService service = new ChromeDriverService.Builder().

                  usingDriverExecutable( new File(chromeDriver) ).build();

ChromeOptions 實例的創建如下:

String chrome = "…\\chrome.exe";

ChromeOptions options = new ChromeOptions();

options.setBinary( chrome );

 

3      基本使用

3.1      打開瀏覽器

開始測試前,總是應該創建一個WebDriver接口實現類實例,以打開某種瀏覽器。

// 創建Firefox driver實例,打開Firefox

WebDriver driver = new FirefoxDriver();

// 創建IE driver實例,打開IE

WebDriver driver = new InternetExplorerDriver();

3.2      打開測試頁面

打開瀏覽器後,應該導航到測試頁面進行測試。

driver.get( "http://www.baidu.com" )

另一種可選方式是:

driver.navigate().to( "http://www.baidu.com" );

3.3      查找元素

導航到測試頁面後,就應該要查找頁面元素進行操作了。

由於Selenium2推崇面向接口編程,所以所有元素都使用WebElement接口代表。

定位元素位置可以在WebDriver實例上進行,也可以在某個WebElement上進行。它們都暴露了findElement()和findElements()方法,前者查找返回一個WebElement對象否則拋出異常;後者查找返回一個WebElement列表,如果沒有匹配項列表可能爲空。

兩種find方法都使用By類實例進行定位。By是一個抽象類,所以實際使用的應是它的派生子類,每種派生子類都代表一種查找策略。通常我們不直接調用其派生子類的構造器創建對象,而是使用By類的靜態工廠方法來創建。

下面逐一說明各種定位方式。

3.3.1       By ID

通過ID查找。這是最高效也最常用的定位方式。但是,可能存在的陷阱是:網頁中ID並非唯一或者ID是自動生成的。使用中應該避免這些情況。

WebElement element = driver.findElement(By.id("coolestWidgetEvah"));

3.3.2       By Name

通過name查找。

WebElement cheese = driver.findElement(By.name("cheese"));

3.3.3       By XPath

通過XPath查找。WebDriver試圖在任何地方使用瀏覽器原生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

比如如下頁面:

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

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

查找語句爲:

List<WebElement> inputs = driver.findElements(By.xpath("//input"));

匹配結果爲:

XPath expression

HtmlUnit Driver

Firefox Driver

Internet Explorer Driver

//input

1 (“example”)

2

2

//INPUT

0

2

0

有時元素不必聲明某些有默認值的屬性,比如input元素的type屬性可以缺省,缺省值爲text。但是在WebDriver中使用XPath時,你不能期望能夠匹配未聲明的默認屬性。

3.3.4       By Class Name

通過class屬性查找。實際使用中相同的class屬性一般對應多個元素,所以一般會查找到多個元素,然後取用第一個元素。

List<WebElement> cheeses = driver.findElements(By.className("cheese"));

3.3.5       By Link Text

通過超鏈接文本查找超鏈接。

WebElement cheese = driver.findElement(By.linkText("cheese"));

3.3.6       By Partial Link Text

通過部分超鏈接文本查找超鏈接。

WebElement cheese = driver.findElement(By.partialLinkText("cheese"));

3.3.7       By Css Selector

通過Css Selector查找。如果瀏覽器默認原生支持css查詢,可參閱w3c css selectors;否則Sizzle被使用。IE6,7和FF3.0都使用Sizzle作爲css查詢引擎。

注意並非所有的瀏覽器都是等效的,有的css在一箇中起作用也許在另一箇中不會。

WebElement cheese = driver.findElement(By.cssSelector("#food span.dairy.aged"));

3.3.8       By TagName

通過元素標籤名查找。

WebElement frame = driver.findElement(By.tagName("iframe"));

3.4      界面操作

找到頁面元素後,需要操作元素,通常WebElement接口方法就足以操作大多數元素了。

3.4.1       通用操作

// 點擊

element.click();

// 文本框輸入

element.sendKeys(“*****”);

// 文本框清空

element.clear();

// 是否選中,單/多選等

element.isSelected();

// 是否可用

element.isEnabled();

3.4.2       文件域

file.sendKeys(filePath);

3.4.3       下拉列表

對於下拉列表這種較複雜的元素,使用通用的方法來操作將不是那麼高效的。我們可以將其封裝爲Select對象,這將提供更多有用的方法便於操作。

Select select = new Select(driver.findElement(By.tagName("select")));

select.selectByVisibleText(“***”);

select.deselectByVisibleText(“***”);

select.selectByValue(“***”);

select.deselectByValue(“***”);

select.deselectAll();

select.getAllSelectedOptions();

select.getFirstSelectedOption();

3.4.4       表單

一旦填寫完表單,我們就期望提交它。一個提交的方法是找到“提交”按鈕並點擊它。

driver.findElement(By.id("submit")).click();

另外,WebDriver爲每個元素都提供了一個方便的submit()方法。如果你調用一個處於表單中的元素的submit()方法,WebDriver將沿DOM向上查找直到找到表單然後提交。如果元素不在表單中,則會拋出NoSuchElementException異常。

// 表單提交

element.submit();

3.4.5       Actions

// 拖拽元素到目標元素中

new Actions( driver ).dragAndDrop( element, target ).perform();

// hover

new Actions(driver).moveToElement( text ).perform();

3.4.6       對話框

我們可以獲取到各種彈出對話框的對象,並可以執行accept、dismiss、讀取內容或者向prompt中輸入內容等操作。

Alert alert = driver.switchTo().alert();

alert.accept();

alert.dismiss();

alert.getText();

alert. sendKeys();

3.4.7       Windows和Frames切換

有的Web應用是多框架或多窗口的。

WebDriver支持在命名窗口間切換:

driver.switchTo().window("windowName");

怎樣知道窗口的名字呢?查看一下打開它的JS或超鏈接:

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

3.4.8       導航

driver.navigate().forward();

driver.navigate().back();

 

4      非界面操作

4.1      Cookie

driver.manage().addCookie(cookie);

driver.manage().getCookies();

driver.manage().getCookieNamed(“cookieName”);

driver.manage().deleteCookieNamed(“cookieName”);

driver.manage().deleteCookie(cookie);

driver.manage().deleteAllCookies();

4.2      執行JS

可以執行任意JS腳本來查找一個元素,並且只要返回一個DOM元素,它將被自動轉換爲WebElement對象。

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

 

4.3      截圖

測試過程中,可以把頁面截圖,保存成爲圖片。

需要注意,截取的圖片存在臨時目錄,所以需要將其拷貝到指定的目錄,否則測試完成可就找不到截圖了。

File screenshotFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);

FileUtils.copyFile( screenshotFile, new File("E:\\1.png") );

或遠程截圖

WebDriver augmentedDriver = new Augmenter().augment(getDriver());

File screenshotFile = ((TakesScreenshot)augmentedDriver).getScreenshotAs(OutputType.FILE);

 

4.4      等待

當頁面需要一段時間才能加載完成,那麼就需要等待完成後才進行查找和操作。

等待有2種:顯性等待和隱性等待。

顯性等待使用WebDriverWait類和ExpectedCondition接口完成,編碼實現ExpectedCondition接口用以判斷某種條件,然後等待這種條件達成或超時。

WebElement myDynamicElement = (new WebDriverWait(driver, 10))

  .until(ExpectedConditions.presenceOfElementLocated(By.id("myDynamicElement")));

ExpectedConditions類提供了許多靜態工廠方法,返回常用的ExpectedCondition對象。

隱性等待更爲簡潔:

driver.manage().timeouts().implicitlyWait( 10, TimeUnit.SECONDS );

但是隱性等待的設置將影響後續全局的查找操作。

4.5      改變User Agent

FirefoxProfile profile = new FirefoxProfile();

profile.addAdditionalPreference("general.useragent.override", "some UA string");

WebDriver driver = new FirefoxDriver(profile);

 

5      附錄

5.1      注意

5.1.1       關於click()

當調用WebElement.click()時,如果被操作元素是不可用的(disabled),click()方法調用仍會是正常的,不會有異常。

所以,如果會出現被點擊的元素是不可用的情況,而點擊不可用元素又被認爲是非法的,那麼應該在click()調用前使用isEnable()方法檢查元素可用性。

5.1.2       driver.close() vs.driver.quit()

在測試結束後通常需要關閉瀏覽器,這個操作通常使用close()或quit()方法完成。但是兩者是有區別的,其方法說明也體現了這一點。

close()

Close the current window, quitting the browser if it's the last window currently open.

quit()

Quits this driver, closing every associated window.

對於close()而言,如果當前窗口是最後一個打開窗口,那麼關閉當前窗口退出瀏覽器;quit()則關閉每個關聯的窗口退出瀏覽器。

但是,實際使用中close()方法的行爲同說明有一些出入。以firefox爲例,噹噹前窗口爲最後一個打開窗口時,close()方法不會將最後一個窗口關閉,當然也不會使firefox退出。

5.2      常用API

5.2.1       Sleeper

原生休眠類

org.openqa.selenium.browserlaunchers.Sleeper

public static void sleepTightInSeconds(longtimeoutInSeconds)

public static void sleepTight(long timeout)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章