亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

selenium從入門到應用 - 5,頁面對象設計模式下

系統 2568 0

本系列所有代碼?https://github.com/zhangting85/simpleWebtest

本文將介紹一個Java+TestNG+Maven+Selenium的web自動化測試腳本環境下selenium頁面對象設計下的頁面模塊的寫法,并提供全部代碼。

?

在一個頁面上,有的時候,會有一些需要重復利用的模塊。

比如,一個電子商務網站上,經常會在頁面最頂上有一個搜索框。這個搜索框在幾乎所有頁面上都會出現。可以隨時用它搜索一些商品。

這里,有人用繼承,寫一個父類,父類提供了這個搜索框的一些功能封裝。然后所有頁面類都繼承這個父類。

這樣寫一開始是沒問題的。但是當這類重用模塊增加了,變動了,會造成整個測試代碼邏輯結構亂成一團。所以不推薦。

?

這里介紹一下我的寫法:

把這些重復利用的部分作為頁面模塊。然后我對京東的首頁、搜索結果頁建立了頁面對象模型:

代碼如下:

?

首頁

        
           1
        
        
          /**
        
        
           2
        
        
           *京東首頁


        
        
           3
        
        
          */
        
        
           4
        
        
          public
        
        
          class
        
         JDHomepage 
        
          extends
        
        
           Page {


        
        
           5
        
        
          /**
        
        
           6
        
        
           *URL常量,很少用到,一般在起始頁用,有時放到配置文件里去統一管理


        
        
           7
        
        
          */
        
        
           8
        
        
          private
        
        
          static
        
        
          final
        
         String URL="http://www.jd.com"
        
          ;


        
        
           9
        
        
          10
        
        
          /**
        
        
          11
        
        
           *可供重用的頁面模塊,作為成員對象在顯示這個模塊的頁面中保存。


        
        
          12
        
        
           *這里用了組合的寫法(composite),注意不要濫用繼承。


        
        
          13
        
        
          */
        
        
          14
        
        
          public
        
         SearchHeaderModule searchHeader=
        
          new
        
        
           SearchHeaderModule();


        
        
          15
        
        
          16
        
        
          /**
        
        
          17
        
        
           * 只有homepage之類的起始頁才必要有這個init方法用來打開URL。


        
        
          18
        
        
           * return this 表示執行完畢之后頁面仍舊在本頁。


        
        
          19
        
        
           * 如果留在本頁,并有頁面刷新,就要return new JDHomepage


        
        
          20
        
        
           * 如果沒有頁面刷新等頁面改變,就return this


        
        
          21
        
        
           * 如果跳轉到其他頁面,就return new xxxPage


        
        
          22
        
        
           * 這樣寫的好處,是每個方法的return語句上明確了頁面跳轉的預期結果


        
        
          23
        
        
           * Only the start page of a test case should has this init method


        
        
          24
        
        
           * 
        
        
          @return
        
        
           return this means no page refresh and stay on this page after this method


        
        
          25
        
        
           * return new JDHomepage means stay on this page and has a page refresh


        
        
          26
        
        
           * return new xxxPage means page redirects after this method


        
        
          27
        
        
          */
        
        
          28
        
        
          public
        
        
           JDHomepage init(){


        
        
          29
        
        
              DriverManager.driver.get(URL);


        
        
          30
        
        
          return
        
        
          this
        
        
          ;


        
        
          31
        
        
          }


        
        
          32
        
        
          33
        
        
          34
        
        
          35
        
         }
      
View Code

在首頁里我其實沒有封裝什么業務邏輯,正常來說如果實際去實現整個京東的測試用例,那么首頁這個類會變得比較龐大的。

這里我用下面這段代碼創建了SearchHeader這個頁面模塊

      
        public
      
       SearchHeaderModule searchHeader=
      
        new
      
       SearchHeaderModule();
    

作為一個成員對象。這個對象的實例會在JDHomepage的構造方法被調用前先被jvm調用。

所以,每個Homepage的實例都會包含一個SearchHeader,然后我們只使用時如下調用即可:

      home.init().searchHeader.search("巧克力");
    

home是一個JDHomepage類的實例,init方法是去打開這個page的URL,我只在首頁等起始頁上寫init方法。

search是searchHeader提供的方法,這樣直接連點調用即可。

?

SearchHeader的實現:

        
           1
        
        
          package
        
        
           simplewebtest.core.page.module.sample.jd;


        
        
           2
        
        
           3
        
        
          import
        
        
           org.openqa.selenium.WebElement;


        
        
           4
        
        
          import
        
        
           org.openqa.selenium.support.FindBy;


        
        
           5
        
        
           6
        
        
          import
        
        
           simplewebtest.core.Page;


        
        
           7
        
        
          import
        
        
           simplewebtest.core.page.sample.jd.JDItemlistPage;


        
        
           8
        
        
           9
        
        
          10
        
        
          /**
        
        
          11
        
        
           * 頁面模塊。此處表示京東各頁面上方共享的搜索條


        
        
          12
        
        
           * 他本身也可以看做是一個頁面


        
        
          13
        
        
           * 并以組合(composite)的形式嵌入外部網頁,注意不要濫用繼承


        
        
          14
        
        
           * this page module is composite to the outer page


        
        
          15
        
        
          */
        
        
          16
        
        
          public
        
        
          class
        
         SearchHeaderModule 
        
          extends
        
        
           Page {


        
        
          17
        
        
          18
        
        
          /**
        
        
          19
        
        
               * PageFactory的寫法,用標簽來定義web elment的查找 define how to find a webelment by


        
        
          20
        
        
               * annotation


        
        
          21
        
        
          */
        
        
          22
        
             @FindBy(id = "key"
        
          )


        
        
          23
        
        
              WebElement searchInput;


        
        
          24
        
        
          25
        
             @FindBy(xpath = "http://input[@value='搜索']"
        
          )


        
        
          26
        
        
              WebElement searchButton;


        
        
          27
        
        
          28
        
        
          /**
        
        
          29
        
        
               * 搜索一個關鍵字,先輸入文字,再按搜索按鈕 search a keyword


        
        
          30
        
        
               * 


        
        
          31
        
        
               * 
        
        
          @param
        
        
           keyword


        
        
          32
        
        
               *            :搜索關鍵字


        
        
          33
        
        
               * 
        
        
          @return
        
        
           返回一個JDItemlistPage


        
        
          34
        
        
          */
        
        
          35
        
        
          public
        
        
           JDItemlistPage search(String keyword) {


        
        
          36
        
        
                  searchInput.sendKeys(keyword);


        
        
          37
        
        
                  searchButton.click();


        
        
          38
        
        
          return
        
        
          new
        
        
           JDItemlistPage();


        
        
          39
        
        
              }


        
        
          40
        
         }
      
View Code

這個SearchHader就是一個普通的頁面對象。

注意所有的頁面對象里的封裝方法我都讓他返回類似 new JDItemlistPage()之類的頁面對象。

這樣我們在test case里可以連點。比如

      home.init().searchHeader.search("巧克力").getProduct(1).getText();
    

至于連點造成調試困難?不,由于我們有事件監聽和自動log功能,調試不會很困難。

并且我通常是先寫線性代碼再重構成頁面對象,寫成這種的都是已經執行通過的代碼。

另外,我們不是每次都需要返回新的頁面對象實例,因為有時比做一個操作,頁面不會跳轉也不會變動。這時,return this;返回當前頁的實例就行了。

?

JDItemlistPage

        
           1
        
        
          package
        
        
           simplewebtest.core.page.sample.jd;


        
        
           2
        
        
           3
        
        
          import
        
        
           java.util.List;


        
        
           4
        
        
           5
        
        
          import
        
        
           org.openqa.selenium.By;


        
        
           6
        
        
          import
        
        
           org.openqa.selenium.WebElement;


        
        
           7
        
        
          import
        
        
           org.openqa.selenium.support.FindBy;


        
        
           8
        
        
           9
        
        
          import
        
        
           simplewebtest.core.Page;


        
        
          10
        
        
          /**
        
        
          11
        
        
           *京東搜索商品結果頁


        
        
          12
        
        
          */
        
        
          13
        
        
          public
        
        
          class
        
         JDItemlistPage 
        
          extends
        
        
           Page {


        
        
          14
        
        
          15
        
        
          16
        
        
          /**
        
        
          17
        
        
               *先找所有商品的父親節點plist


        
        
          18
        
        
          */
        
        
          19
        
             @FindBy(id = "plist"
        
          )


        
        
          20
        
        
          public
        
        
           WebElement productList;


        
        
          21
        
        
          22
        
        
          /**
        
        
          23
        
        
               *直接找第一個商品,XPATH表達式過長,無法閱讀。(你會看得頭疼嗎?我會。。。)


        
        
          24
        
        
               *注意這個xpath是由firepath自動生成的,冗余過度。如果你要用xpath,一定要會自己寫


        
        
          25
        
        
               *插件太傻,別依賴他。


        
        
          26
        
        
          */
        
        
          27
        
             @FindBy(xpath = ".//*[@id='plist']/ul/li[1]/div/div[2]/a"
        
          )


        
        
          28
        
        
          public
        
        
           WebElement firstproduct;


        
        
          29
        
        
          30
        
        
          /**
        
        
          31
        
        
               *預先定位所有product


        
        
          32
        
        
               *get all products, suggested to use this way


        
        
          33
        
        
          */
        
        
          34
        
             @FindBy(xpath = ".//*[@id='plist']//li"
        
          )


        
        
          35
        
        
          public
        
         List<WebElement>
        
           products;


        
        
          36
        
        
          37
        
        
          /**
        
        
          38
        
        
               *先找父親plist,讓父親來找兒子,這種寫法也是可以的,但是也不是特別好(這一定不是強迫癥)


        
        
          39
        
        
               *但是這個方法只能找第一個商品,想找第二個商品要再寫一個方法。不推薦。     


        
        
          40
        
        
          */
        
        
          41
        
        
          public
        
        
           String getFirstProductName() {


        
        
          42
        
        
          return
        
         productList.findElement(By.xpath("http://div[@class='p-name'][1]//a"
        
          )).getText();


        
        
          43
        
        
              }


        
        
          44
        
        
          45
        
        
          /**
        
        
          46
        
        
               *先找父親plist,讓父親來找兒子,但是加了一個傳入參數告訴父親要找第幾個兒子,也就是第幾個商品。(圣斗士嗎,這么多兒子)


        
        
          47
        
        
               *這樣我寫一次可以找到這個頁面上任意一個商品了,京東的網頁設計特別適合自動化,可能你要測的網站不是這么工整。


        
        
          48
        
        
               *這里的重點是:Xpath表達式是一個字符串,你可以隨意拼接。所以傳入參數number可以插進去。


        
        
          49
        
        
               *suggested


        
        
          50
        
        
          */
        
        
          51
        
        
          public
        
         String getProductNameByIndexMethodOne(
        
          int
        
        
           number) {


        
        
          52
        
        
          return
        
         productList.findElement(By.xpath("http://div[@class='p-name']["+number+"]//a"
        
          )).getText();


        
        
          53
        
        
              }


        
        
          54
        
        
          55
        
        
          /**
        
        
          56
        
        
               *一次性找出所有product,然后取第幾個,我喜歡從1開始所以number-1,僅個人喜好。


        
        
          57
        
        
               *接著對找到的product執行getProductNameOf方法來獲取名字


        
        
          58
        
        
               *suggested


        
        
          59
        
        
          */
        
        
          60
        
        
          public
        
         String getProductNameByIndexMethodTwo(
        
          int
        
        
           number) {    


        
        
          61
        
        
          return
        
         getProductNameOf(products.get(number-1
        
          ));


        
        
          62
        
        
              }


        
        
          63
        
        
          64
        
        
          private
        
        
           String getProductNameOf(WebElement product)


        
        
          65
        
        
              {


        
        
          66
        
        
          return
        
         product.findElement(By.className("p-name"
        
          )).getText();


        
        
          67
        
        
          68
        
        
              }


        
        
          69
        
        
          70
        
        
          71
        
         }
      
View Code

這個頁面就是一個標準的頁面對象了

為了擴展一下,我增加了一些內容,比如尋找第一個商品的四種方法:

              JDHomepage home = 
      
        new
      
      
         JDHomepage();

        

        
      
      
        //
      
      
        結果頁面the expected result page 
      
      

        JDItemlistPage resultPage=home.init().searchHeader.search("巧克力"
      
        );

        
      
      
        //
      
      
        actual result: 用四種方法找出第一個商品名字,作為實際結果.(回字有五種寫法:P)
      
      
            

        String product_1
      
      = resultPage.firstproduct.getText();
      
        //
      
      
        不推薦,但偶爾有適用場景
      
      

        String product_2= resultPage.getFirstProductName();
      
        //
      
      
        不推薦,但偶爾有適用場景
      
      

        String product_3= resultPage.getProductNameByIndexMethodOne(1);
      
        //
      
      
        推薦寫法,但你方法名字不要這么長
      
      

        String product_4= resultPage.getProductNameByIndexMethodTwo(1);
      
        //
      
      
        推薦寫法,但你方法名字不要這么長
      
    

?

如上代碼中,(和JDItemlistPage的代碼結合起來看)

方法1直接用PageObject.WebElement來獲取商品,缺點是每個商品我都要定義一個WebElement

方法2先找到product list,再用一句寫死的Xpath來尋找第一個商品,缺點是個商品我都要寫一段寫死的Xpath

方法3先找到product list,再通過傳入參數來組合一段可用的Xpath,優點是我只要寫一次Xpath

方法4先找到所有product:

      @FindBy(xpath = ".//*[@id='plist']//li"
      
        )

    
      
      
        public
      
       List<WebElement> products;
    

然后再蔥存放WebElement的List里取第一個元素。我同樣要寫一次By.className定位。

?

對于尋找商品這樣的例子來說,推薦用方法3或4。對于一般的頁面元素推薦用方法1。對于一些其他特殊的場景,看情況使用方法2。

另外,JDItemListPage里也可以像首頁一樣加入一個SearchHeader的定義,這里沒加只是因為目前我用到的test case里沒有這個需要。

?

selenium從入門到應用 - 5,頁面對象設計模式下的頁面模塊


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 97免费观看视频 | 狠狠色噜噜狠狠狠狠网站视频 | 久久福利一区二区三区 | 一级做a爰片性色毛片2021 | 四虎精品久久久久影院 | 国产欧美一区二区三区视频 | 亚洲日韩成人 | 欧美日韩在线成人免费 | 福利在线播放 | 欧美日本俄罗斯一级毛片 | 国产精品伦理一二三区伦理 | 成人午夜天 | 国产精品二| 欧美精品在线一区二区三区 | 性色生活免费看性大片 | 成人久久久精品乱码一区二区三区 | 四虎www成人影院 | 久久久久亚洲精品美女 | 亚洲欧美日韩中文字幕在线一区 | 在线观看精品91老司机 | 五月婷婷伊人 | 久久99热久久精品动漫 | 国产精品久久久久久久hd | 99国产精品欧美久久久久久影院 | 99久久免费精品高清特色大片 | 亚洲资源站资源网在线 | 国产理论视频在线观看 | 国产三级观看久久 | 日日网站 | 四虎网址最新 | 国产成人一区二区视频在线观看 | 日本欧美一区二区三区不卡视频 | 成人欧美精品一区二区不卡 | 一级女人18毛片免费 | 中文字幕在线不卡视频 | 尤物福利视频 | 羞羞网站在线看 | 久久精品re | 午夜视频网址 | 亚洲激情视频在线播放 | 国产精品免费视频一区 |