Selenium WebDriver 之 PageObjects 模式 by Example

目錄
  1. 項目配置
  2. 一個WebDriver簡單例子
  3. 使用Page Objects模式
  4. 總結
  5. Troubleshooting
  6. 參考文檔

本篇文章經過例子來闡述一下Selenium2.0 WebDriver 之 Page Objects模式。javascript

 

項目配置

maven 3, pom.xml配置以下css

<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>2.46.0</version>
</dependency>

另外我是用TestNG 寫Selenium tests, 加以下dependencyhtml

<dependency>
    <groupId>org.testng</groupId>
    <artifactId>testng</artifactId>
    <version>6.8</version>
</dependency>

 

一個WebDriver簡單例子

主要作以下幾個動做:java

1. 打開博客園首頁web

2. 斷言頁面標題出現api

3. 在找找看輸入框輸入字符瀏覽器

4. 點擊找找看按鈕網絡

5. 斷言進入的頁面標題async

 1 package test.demo;
 2 
 3 import static org.testng.Assert.assertEquals;
 4 
 5 import org.openqa.selenium.By;
 6 import org.openqa.selenium.WebDriver;
 7 import org.openqa.selenium.WebElement;
 8 import org.openqa.selenium.firefox.FirefoxDriver;
 9 import org.openqa.selenium.firefox.FirefoxProfile;
10 import org.testng.annotations.AfterTest;
11 import org.testng.annotations.BeforeTest;
12 import org.testng.annotations.Test;
13 
14 ;
15 
16 /**
17  * @Description: A simple Test using WebDriver
18  * @author wadexu
19  * 
20  * @updateUser
21  * @updateDate
22  */
23 public class WebPageTest {
24 
25     private WebDriver driver;
26 
27     @BeforeTest
28     public void setUp() {
29         FirefoxProfile firefoxProfile = new FirefoxProfile();
30         // use proxy
31         firefoxProfile.setPreference("network.proxy.type", 1);
32         firefoxProfile.setPreference("network.proxy.http", "10.51.1.140");
33         firefoxProfile.setPreference("network.proxy.http_port", "8080");
34 
35         driver = new FirefoxDriver(firefoxProfile);
36     }
37 
38     @AfterTest
39     public void tearDown() {
40         driver.close();
41     }
42 
43     @Test
44     public void test() {
45         driver.get("http://www.cnblogs.com/");
46         assertEquals("博客園 - 開發者的網上家園", driver.getTitle());
47 
48         WebElement searchBox = driver.findElement(By.id("zzk_q"));
49         searchBox.sendKeys("wadexu");
50 
51         WebElement searchBtn = driver.findElement(By.xpath("//*[@id='search_block']/div[1]/input[2]"));
52         searchBtn.click();
53 
54         assertEquals("wadexu-博客園找找看", driver.getTitle());
55     }
56 
57 }

這種寫法缺點不少, 可讀性差,頁面元素,操做HTML,測試邏輯所有在一塊兒。maven

##轉載註明出處:http://www.cnblogs.com/wade-xu/p/4744937.html 

 

使用Page Objects模式

PageObjects是對具體頁面的抽象,使用時經過PageFactory來構造。

首先咱們爲博客園首頁和找找看搜索頁面定義兩個page objects

-- CnBlogsHomePage

 1 package test.demo;
 2 
 3 import org.openqa.selenium.WebElement;
 4 import org.openqa.selenium.support.FindBy;
 5 
 6 /**
 7  * @Description: 博客園首頁
 8  * @author wadexu
 9  *
10  * @updateUser
11  * @updateDate
12  */
13 public class CnBlogsHomePage {
14 
15     @FindBy(id = "zzk_q") //找找看輸入框
16     protected WebElement searchBox;
17     
18     @FindBy(xpath = "//*[@id='search_block']/div[1]/input[2]") //找找看按鈕
19     protected WebElement searchBtn;
20     
21     public void searchFor(String content) {
22         searchBox.sendKeys(content);
23         searchBtn.click();
24     }
25 }

 

-- SearchResultPage

package test.demo;

import java.util.List;

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;

/**
 * @Description: 博客園找找看頁面
 * @author wadexu
 *
 * @updateUser
 * @updateDate
 */
public class SearchResultPage {

    @FindBy(id = "searchResult") 
    protected WebElement searchResult;
    
    //for tutorial purpose only
    public boolean searchResultListNotNull() {
        WebElement searchResultItems = searchResult.findElement(By.cssSelector(".forflow"));
        List<WebElement> resultItemTitleList = searchResultItems.findElements(By.tagName("a"));
        
        for (WebElement e : resultItemTitleList) {
            System.out.println(e.getText());
        }
        
        return resultItemTitleList.size() > 0;
    }
}

##轉載註明出處:http://www.cnblogs.com/wade-xu/p/4744937.html 

 

下面是使用Page Objects 的測試

 1 package test.demo;
 2 
 3 import static org.testng.Assert.assertTrue;
 4 
 5 import org.openqa.selenium.WebDriver;
 6 import org.openqa.selenium.firefox.FirefoxDriver;
 7 import org.openqa.selenium.firefox.FirefoxProfile;
 8 import org.openqa.selenium.support.PageFactory;
 9 import org.testng.annotations.AfterTest;
10 import org.testng.annotations.BeforeTest;
11 import org.testng.annotations.Test;
12 
13 /**
14  * @Description: UsingPageObjectsTest
15  * @author wadexu
16  * 
17  * @updateUser
18  * @updateDate
19  */
20 public class UsingPageObjectsTest {
21 
22     private WebDriver driver;
23 
24     @BeforeTest
25     public void setUp() {
26         FirefoxProfile firefoxProfile = new FirefoxProfile();
27         // use proxy
28         firefoxProfile.setPreference("network.proxy.type", 1);
29         firefoxProfile.setPreference("network.proxy.http", "10.51.1.149");
30         firefoxProfile.setPreference("network.proxy.http_port", "8080");
31 
32         driver = new FirefoxDriver(firefoxProfile);
33     }
34 
35     @AfterTest
36     public void tearDown() {
37         driver.close();
38     }
39 
40     @Test
41     public void test() {
42         driver.get("http://www.cnblogs.com/");
43         CnBlogsHomePage homePage = PageFactory.initElements(driver, CnBlogsHomePage.class);
44         homePage.searchFor("wadexu");
45 
46         SearchResultPage resultPage = PageFactory.initElements(driver, SearchResultPage.class);
47         assertTrue(resultPage.searchResultListNotNull());
48     }
49 
50 }

WebDriver爲了支持PageObject模式,支持庫包含一個叫PageFactory的工廠類, 咱們經過PageFactory的initElements方法來實例化PageObject的實例.

這種方式看上去簡潔明瞭,可讀性高,封裝了界面交互細節,可使測試更關注業務邏輯而非頁面細節,就像在寫功能測試用例。

 

Run as TestNG 測試結果以下

就是這麼簡單!使用Rest-assured 測試Restful Web Services
WadeXu
這些年咱們一塊兒搞過的持續集成~Jenkins+Perl and Shell script
WadeXu
Postman (Chrome插件)
HackerVirus
VC/MFC如何設置對話框背景顏色
youxin
玩轉單元測試之DBUnit
WadeXu
性能分析神器VisualVM
WadeXu
性能分析神器VisualVM
qingchen1984
玩轉單元測試之WireMock -- Web服務模擬器
WadeXu
寫在離職前夕
平靜緩和用胸音說愛
帶你入門帶你飛Ⅰ 使用Mocha + Chai + Sinon單元測試Node.js
WadeXu
PASSED: test

===============================================
    Default test
    Tests run: 1, Failures: 0, Skips: 0
===============================================

[TestNG] Time taken by org.testng.reporters.JUnitReportReporter@288051: 4 ms
[TestNG] Time taken by org.testng.reporters.SuiteHTMLReporter@4d865b28: 28 ms
[TestNG] Time taken by org.testng.reporters.XMLReporter@45d64c37: 6 ms
[TestNG] Time taken by [TestListenerAdapter] Passed:0 Failed:0 Skipped:0]: 0 ms
[TestNG] Time taken by org.testng.reporters.EmailableReporter@68e6ff0d: 3 ms

##轉載註明出處:http://www.cnblogs.com/wade-xu/p/4744937.html 

運行的很慢, 主要是由於博客園的頁面加載的許多Script 都是在線引入,不少這種source <script async="" type="text/javascript" src="http://www.googletagservices.com/tag/js/gpt.js"></script>

而我又不能禁用script,不然點不了找找看button。

測試截圖

 

總結

本文咱們學到的知識點有:

  • 使用Selenium WebDriver查找元素,經過By id, xpath, cssSelector, tagName 例子裏儘量的運用了這些方式。
  • 經過FirefoxProfile 設置代理, 也能夠設置頁面不加載一些對象如image, script, stylesheet 設置方式:firefoxProfile.setPreference("permissions.default.image", 2); //2表示關閉
  • Page Objects模式, 優勢不少,分離頁面元素及操做元素的步驟,便於維護, 下降代碼冗餘度,提高複用率。

 

(此圖來源於網絡)

##轉載註明出處:http://www.cnblogs.com/wade-xu/p/4744937.html 

 

Troubleshooting

1. org.openqa.selenium.firefox.NotConnectedException: Unable to connect to host 127.0.0.1 on port 7055 after 45000 ms

firefox瀏覽器版本過高,selenium不兼容,要麼下降firefox的版本,要麼用新的selenium webDriver

 

2. Selenium WebDriver正常打開瀏覽器,可是沒法訪問頁面

跟環境有關,使用FirefoxProfile setPreference 設置個代理, 有幾種方式供參考

WebDriver每次啓動一個Firefox的實例時,會生成一個匿名的profile,並不會使用當前Firefox的profile。這點必定要注意。好比若是訪問被測試的web服務須要經過代理,你想直接設置Firefox的代理是行不通的,由於WebDriver啓動的Firefox實例並不會使用你這個profile,正確的作法是經過FirefoxProfile來設置。

 

3. org.openqa.selenium.NoSuchElementException: Unable to locate element

代碼問題,不能定位元素

 

參考文檔

SeleniumHQ Website

Selenium API JavaDocs

 

感謝閱讀,若是您以爲本文的內容對您的學習有所幫助,您能夠點擊右下方的推薦按鈕,您的鼓勵是我創做的動力。

##轉載註明出處:http://www.cnblogs.com/wade-xu/p/4744937.html 

相關文章
相關標籤/搜索