zoukankan      html  css  js  c++  java
  • Selenium WebDriver 之 PageObjects 模式 by Example

    目录
      1. 项目配置
      2. 一个WebDriver简单例子
      3. 使用Page Objects模式
      4. 总结
      5. Troubleshooting
      6. 参考文档

    本篇文章通过例子来阐述一下Selenium2.0 WebDriver 之 Page Objects模式。

    项目配置

    maven 3, pom.xml配置如下

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

    另外我是用TestNG 写Selenium tests, 加如下dependency

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

    一个WebDriver简单例子

    主要做如下几个动作:

    1. 打开博客园首页

    2. 断言页面标题出现

    3. 在找找看输入框输入字符

    4. 点击找找看按钮

    5. 断言进入的页面标题

     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,测试逻辑全部在一起。

    ##转载注明出处: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 

  • 相关阅读:
    (转载)Linux定时任务cron配置
    (转载)PHP源代码分析- tick(s)
    (转载)PCNTL函数族--PHP多进程编程
    org.apache.hadoop.conf-Configured
    org.apache.hadoop.conf-Configuration
    org.apache.hadoop.conf-Configurable
    源码-hadoop1.1.0-core-org.apache.hadoop.classification
    源码-hadoop1.1.0-core-org.apache.hadoop
    作为开始
    测试一下
  • 原文地址:https://www.cnblogs.com/wade-xu/p/4744937.html
Copyright © 2011-2022 走看看