跟浩哥學自動化測試Selenium -- 瀏覽器的基本操作與元素定位(3)


瀏覽器的基本操作與元素定位

      通過上一章學習,我們已經學會了如何設置驅動路徑,如何創建瀏覽器對象,如何打開一個網站,接下來我們要進行一些復雜的操作比如先打開百度首頁,在打開博客園,網頁后退,前進等等,甚至可以獲取一些瀏覽器信息等等。

   首先看一個基本的例子,流程如下:

  1. 打開百度的網站
  2. 獲取到百度首頁的Title
  3. 獲取當前頁面的URL
  4. 獲取頁面的html信息

    對應的代碼如下:

public class SeleniumTest {
    public static void main(String... args){
        System.setProperty("webdriver.gecko.driver","c:\\geckodriver.exe");
        WebDriver webDriver = new FirefoxDriver();
        webDriver.get("http://www.baidu.com");
        System.out.println(webDriver.getTitle());//獲取首頁的Title
        System.out.println(webDriver.getCurrentUrl());//獲取當前url
        System.out.println(webDriver.getPageSource());//獲取頁面的html信息
    }
}

   再來看一個例子,操作流程如下:

  1. 打開百度首頁
  2. 打開我的博客頁面
  3. 后退到百度頁面
  4. 前進到博客頁面
  5. 刷新頁面
  6. 關閉頁面

    對應的代碼如下:

public class SeleniumTest {
    public static void main(String... args){
        System.setProperty("webdriver.gecko.driver","c:\\geckodriver.exe");
        WebDriver webDriver = new FirefoxDriver();
        webDriver.navigate().to("http://www.baidu.com");
        webDriver.navigate().to("https://www.cnblogs.com/jacktest");
        webDriver.navigate().back();//后退
        webDriver.navigate().forward();//前進
        webDriver.navigate().refresh();//刷新
        webDriver.close();//關閉瀏覽器
        webDriver.quit();//關閉瀏覽器以及驅動
    }
}

   close 和 quit區別:close 只會關閉當前瀏覽器,而quit不僅會關閉瀏覽器也會殺掉驅動進程。close的問題在於你多次進行調試時,進程中會殘留多個驅動進程,這種情況有可能會引起一些其他的問題,建議使用quit。

   源碼分析,close和quit在發送 HttpRequest 請求時,method 都是DELETE ,但uri不同,如下:

   close的HttpRequest

   

      quit 的HttpRequest

       

 

   最后看一個例子,基礎元素定位,流程如下:

  1. 打開百度首頁
  2. 點擊登錄鏈接
  3. 輸入用戶名、密碼
  4. 點擊登錄 

   對應的代碼如下:

public class SeleniumTest {
    public static void main(String... args) throws InterruptedException {
        System.setProperty("webdriver.gecko.driver", "C:\\driver\\geckodriver.exe");
        WebDriver webDriver = new FirefoxDriver();
        webDriver.manage().window().maximize();//瀏覽器最大化
        webDriver.get("https://www.baidu.com");
        webDriver.findElement(By.xpath("//div[@id='u1']/a[@name='tj_login']")).click();//點擊登錄鏈接
        Thread.sleep(1000);
        webDriver.findElement(By.id("TANGRAM__PSP_10__footerULoginBtn")).click();//點擊用戶名登錄
        webDriver.findElement(By.id("TANGRAM__PSP_10__userName")).sendKeys("jacktest");//輸入用戶名
        webDriver.findElement(By.id("TANGRAM__PSP_10__password")).sendKeys("123456");//輸入密碼
        webDriver.findElement(By.id("TANGRAM__PSP_10__submit")).click();//點擊登錄
    }
}

   運行該腳本,我們發現打開了火狐瀏覽器,打開百度首頁,點擊了登錄鏈接,輸入了用戶名、密碼並成功進行了登錄。什么登錄失敗,哈哈,當然,賬號換成你自己的就ok 了。

    代碼分析,在該腳本中,我們看到了Thread.sleep(1000),它的作用是讓腳本執行時暫停1秒,有的同學會問,為什么要暫停呢?因為我的腳本在執行完webDriver.findElement(By.xpath("//div[@id='u1']/a[@name='tj_login']")).click()這條語句后,彈出窗口不會馬上彈出來,大概需要 0.5-1秒的時間,如果在窗口未彈出的情況下執行下一條語句時,就會發生錯誤(org.openqa.selenium.NoSuchElementException異常---找不到元素),所以,我要等待一下,等窗口出現以及頁面上的元素出現就不會出現以上錯誤了。有的同學會問,難道所有的窗口以及元素或頁面都得等待嗎,我們都需要加sleep嗎,浩哥的回答是當然不需要。在腳本調試過程中,只有極個別的情況需要加等待,當然我們也有更好的方式去解決這個問題,比如顯示等待,隱式等待,自定義等待等等。

    接下來,我們再來看幾個常用的方法:

public class SeleniumTest {
    public static void main(String... args) throws InterruptedException {
        System.setProperty("webdriver.gecko.driver", "C:\\driver\\geckodriver.exe");
        WebDriver webDriver = new FirefoxDriver();
        webDriver.manage().window().fullscreen();//瀏覽器全屏,相當於F11
        Point point = new Point(50, 100);
        webDriver.manage().window().setPosition(point);//指定窗口出現的位置
        Dimension dimension = new Dimension(500, 600);
        webDriver.manage().window().setSize(dimension);//指定窗口大小
        WebDriver.ImeHandler imeHandler = webDriver.manage().ime();
        System.out.println(imeHandler.isActivated());//輸入法相關的API,查了一些資料好像只支持linux,有興趣可以自己試試
    }
}

  

         日志相關的API,指的是Selenium原生的日志支持,並不是指比如像 log4j 這樣的外部提供的日志支持。

 
 
public class SeleniumTest {
public static void main(String... args) throws InterruptedException {
System.setProperty("webdriver.gecko.driver", "C:\\driver\\geckodriver.exe");
DesiredCapabilities desiredCapabilities = DesiredCapabilities.firefox();
LoggingPreferences loggingPreferences = new LoggingPreferences();
loggingPreferences.enable(LogType.BROWSER, Level.ALL);
loggingPreferences.enable(LogType.CLIENT, Level.ALL);
loggingPreferences.enable(LogType.DRIVER, Level.ALL);
desiredCapabilities.setCapability(CapabilityType.LOGGING_PREFS, loggingPreferences);
WebDriver webDriver = new FirefoxDriver(desiredCapabilities);
LogEntries logEntries = webDriver.manage().logs().get(LogType.BROWSER);
for (LogEntry logEntry : logEntries) {
System.out.println(logEntry.getMessage()+"--");
}
webDriver.get("https://www.baidu.com");
}
}
 

         自己試驗了一下上述代碼,在Selenium 3.0 之前的版本中可以支持,在之后無法支持,提示org.openqa.selenium.UnsupportedCommandException: POST /session/419bca1f-d33d-46ff-8979-10e88901cd12/log did not match a known command。好像是由於logs 並不支持 W3C 規范,大家也可以試試其他的方法是否支持。如果想關閉運行Selenium的日志輸出,可把loggingPreferences.enable(LogType.BROWSER, Level.OFF)設置成off即可。

    接下來,我們再看一個有關 Session id 相關的 API:

public class SeleniumTest {
    public static void main(String... args) throws InterruptedException {
        System.setProperty("webdriver.gecko.driver", "C:\\driver\\geckodriver.exe");
        WebDriver webDriver = new FirefoxDriver();
        webDriver.get("https://www.baidu.com");
        Set<String> strings = ((FirefoxDriver) webDriver).getLocalStorage().keySet();
        for (String s : strings) {
            System.out.println(s); //輸出結果為BIDUPSID
        }
        System.out.println(((FirefoxDriver) webDriver).getLocalStorage().getItem("BIDUPSID"));//獲取值
    }
}

       有的同學問,輸出結果為什么是BIDUPSID呢,代表什么意思呢,看完后面的內容大家就明白了。

   首先我們先看一下api,根據 Selenium3 官方文檔 LocalStorage 的表示當前在瀏覽器中打開站點的本地存儲,每個站點都有自己的獨立的存儲區域,也就是打開不同的網站 LocalStorage 各不相同,大家可以自行試驗。有的同學會問,那這和 Session id 有什么關系呢,接下來,我們來普及一下 Session 的一些知識。

    Session id 主要是用來維持會話狀態的通信秘鑰,在請求過程中,默認名字SESSIONID,當然也可以自定義命名(百度的Sessionid是自定義命名)。以百度為例,用戶第一次訪問www.baidu.com的時候,由於請求頭(Request Header)中沒有帶BIDUPSID,百度服務器認為這是一個新的會話,會在服務端給這次會話生成一個唯一標識的 Session id,同時會在http請求的(Response header)中將這個 Session id 帶給瀏覽器,反應在請求的Response header,如下:

Set-Cookie:BIDUPSID=EEAE958FDBA12D0BECDA19585965F6E8; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com

         這個Session id 就是 key=BIDUPSID,value=EEAE958FDBA12D0BECDA19585965F6E8 這樣一個結構,瀏覽器接收到 response 中Set-Cookie命令之后,會在瀏覽器設置cookie 值 BIDUPSID=EEAE958FDBA12D0BECDA19585965F6E8,並在以后請求 baidu.com 這類域名時帶上cookie值,既 Request Header 中帶上Cookie:BAIDUID=EEAE958FDBA12D0BECDA19585965F6E8,這樣服務器就可以通過這個秘鑰來識別請求來自哪個用戶了。

         繼續驗證上述問題,打開google瀏覽器,清除百度頁面相關的所有緩存,打開開發者模式,切換到 Network 頁,在瀏覽器中輸入https://www.baidu.com,其中部分請求頁面如下:

    

 

         點擊第一個請求,在Header中進行查看,

General

     Request URL:https://www.baidu.com/
     Request Method:GET
     Status Code:200 OK
     Remote Address:111.13.100.92:443
     Referrer Policy:no-referrer-when-downgrade

Response Headers
   Connection:Keep-Alive
   Content-Length:225
   Content-Type:text/html
   Date:Mon, 09 Jul 2018 07:20:43 GMT
   Location:https://www.baidu.com/
   P3p:CP=" OTI DSP COR IVA OUR IND COM "
   Server:BWS/1.1
   Set-Cookie:BD_LAST_QID=10490791214885359030; path=/; Max-Age=1
   Set-Cookie:BAIDUID=813A9265BC68AC521C003B3ABEFDB222:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
   Set-Cookie:BIDUPSID=D09FD09E7F46EBE0242500D6844DEE1D; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
   Set-Cookie:PSTM=1531120843; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
   X-Ua-Compatible:IE=Edge,chrome=1

Request Header

     Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
     Accept-Encoding:gzip, deflate
     Accept-Language:zh-CN,zh;q=0.9
     Connection:keep-alive
     Host:www.baidu.com
     Upgrade-Insecure-Requests:1
     User-Agent:Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36

         分析如下:由於第一次請求時未存在 BIDUPSID,所以百度服務器認為這是一次新的會話,接着在服務端生成唯一標識Sessionid,既Set-Cookie:BAIDUID命令,下次請求baidu.com的網頁時會帶上這個信息。

    打開另一個Tab頁面,輸入百度首頁,查看 Request Header,信息如下:

General

     Request URL:https://www.baidu.com/
     Request Method:GET
     Status Code:200 OK
     Remote Address:111.13.100.91:443
     Referrer Policy:no-referrer-when-downgrade

Response Headers

     Bdpagetype:1
     Bdqid:0xa07b1f01000072b3
     Cache-Control:private
     Connection:Keep-Alive
     Content-Encoding:gzip
     Content-Type:text/html
     Cxy_all:baidu+7fa1ff7e20dcb627a29697a5f962bcc8
     Date:Mon, 09 Jul 2018 07:43:37 GMT
     Expires:Mon, 09 Jul 2018 07:43:22 GMT
     Server:BWS/1.1
     Set-Cookie:BDSVRTM=0; path=/
     Set-Cookie:BD_HOME=0; path=/
     Set-Cookie:H_PS_PSSID=1425_25810_21083_20719; path=/; domain=.baidu.com
     Strict-Transport-Security:max-age=172800
     Transfer-Encoding:chunked
     Vary:Accept-Encoding
     X-Ua-Compatible:IE=Edge,chrome=1

Request Header

     Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
     Accept-Encoding:gzip, deflate, br
     Accept-Language:zh-CN,zh;q=0.9
     Connection:keep-alive
     Cookie:BAIDUID=813A9265BC68AC521C003B3ABEFDB222:FG=1; BIDUPSID=813A9265BC68AC521C003B3ABEFDB222; PSTM=1531121867; BD_HOME=0; H_PS_PSSID=1425_25810_21083_20719; BD_UPN=12314353; SL_GWPT_Show_Hide_tmp=1; SL_wptGlobTipTmp=1
     Host:www.baidu.com
     Upgrade-Insecure-Requests:1
     User-Agent:Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36

     因為在第一次請求時服務器已經返回了BIDUPSID,所以下一次請求時候直接在request header 中加上了BIDUPSID(Sessionid),既驗證了上述內容。

    關於 Selenium cookie 操作的 API,我們會在之后的API 進行分析,此處先略過。

    通過本章的學習的,我們學會了幾個操作,如何操作瀏覽器,怎么點擊元素(click),怎么輸入數據(sendKeys),元素定位(id的方式),元素定位(xpath的方式)。是不是感覺很簡單,其實 Selenium 的API 中常用方法只有十幾個,使用起來還是蠻簡單的。

    在下一篇 《常用定位模式分析》中,我們會一一介紹所有的元素定位模式。


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
  © 2014-2022 ITdaan.com 联系我们: