1. 程式人生 > >Web自動化測試:xpath & CSS Selector定位

Web自動化測試:xpath & CSS Selector定位

# Xpath 和 CSS Selector簡介 ## CSS Selector CSS Selector和Xpath都可以用來表示XML文件中的位置。CSS (Cascading Style Sheets)是一種樣式表語言,是所有瀏覽器內建的,用於描述以HTML或XML編寫的文件的外觀和樣式。CSS Selector用於選擇樣式化的元素,所以理論上前端人員可以定位 DOM 節點並設定樣式,那麼對於測試人員這些元素也可以定位到。 ## XPath XPath是XML路徑語言,是一種查詢語言,使用路徑表示式瀏覽XML文件中的元素和屬性。XPath標準語法如下: **Xpath=//tagname[@attribute='value']** - \// : 選擇當前節點 - Tagname: 節點標籤名 - @: 選擇屬性 - Attribute: 節點屬性名 - Value: 屬性值 XPath有絕對定位和相對定位兩種,絕對定位使用絕對路徑,缺點是路徑太長,只要一個節點變動就無法定位。以單斜槓(/)開始,表示從根節點開始選擇元素。下面是頁面https://www.baidu.com/上“百度一下”按鈕的絕對路徑: ``` /html/body/div[1]/div[1]/div[5]/div[1]/div/form/span[2]/input ``` ![](https://img2020.cnblogs.com/blog/2229336/202012/2229336-20201220124627534-1631088586.png) 相對路徑以雙斜槓(//)開始,可以從HTML文件的任何位置開始,“百度一下”按鈕的相對路徑可以表示如下 ``` //input[@id="su"] ``` ## Xpath VS. CSS Selector CSS Selector和Xpath幾乎可以定位到所有Web元素(HTML和XML文件元素,Android應用的層級結構使用xml編寫),它們的主要差異包括: 1. XPath通過遍歷的方式從XML文件中選擇節點,CSS Selector是一種匹配模式定位,因此CSS Selector比 XPath 執行效率更高。 2. Xpath可以通過文字來定位,而CSS Selector不能; 3. Xpath可以通過子節點來定位父節點,CSS Selector是前向的,不能利用子節點定位父節點。 4. CSS Selector語法相比Xpath更加簡潔 # Xpath 和 CSS Selector元素定位 接下來對比一下這兩種方法的語法差異,節點的定義我們規定如下: ![](https://img2020.cnblogs.com/blog/2229336/202012/2229336-20201220124638938-899708513.png) ## 兒子元素定位 xpath使用‘/’,CSS Selector使用‘>’ | | Xpath | CSS Selector | | ---- | ---------------------------------------- | ------------------- | | 語法 | //*element/element* | *element*>*element* | | 示例 | //div/a | div > a | | 描述 | 選擇父元素為 \ 元素的所有 \ 元素。 | | 還可以使用XPath Axes(軸)**child** 來定位子元素 XPATH: ```python //div/child::*   # 選擇父元素為 元素的所有兒子元素 //div/child::a  # 選擇父元素為 元素的所有元素 ``` CSS Selector: ```python div > a:nth-child(2) # 選擇父元素為 元素的第二個元素 div > a:nth-last-child(2) # 選擇父元素為 元素的倒數第二個元素 div > a:last-child # 選擇父元素為 元素的最後一個元素 div > a:first-child # 選擇父元素為 元素的第一個元素 ``` ## 子孫元素定位 xpath使用‘//’,CSS Selector使用空格 | | **Xpath** | **CSS Selector** | | -------- | ------------------------------------ | ----------------- | | **語法** | //*element//element* | *element element* | | **示例** | //div//a | div a | | **描述** | 選擇 \ 元素內部的所有 \ 元素。 | | 還可以使用XPath Axes(軸)**descendant** 來定位子孫元素 XPATH: ```python //div/descendant::*   # 選擇祖先元素為 元素的所有子孫元素 //div/descendant::a  # 選擇祖先元素為 元素的所有元素    ``` CSS Selector使用空格定位子孫元素後進行選擇: ```python div a:nth-child(2) # 選擇祖先元素為 元素的第二個元素 div a:nth-last-child(2) # 選擇祖先元素為 元素的倒數第二個元素 div a:last-child # 選擇祖先元素為 元素的最後一個元素 div a:first-child # 選擇祖先元素為 元素的第一個元素 ``` ## 鄰居節點定位 在同一個父節點下,定位下一個相鄰節點 | | **Xpath** | **CSS Selector** | | -------- | ------------------------------------------ | ------------------- | | **語法** | //*element/following-sibling::element* | *element + element* | | **示例** | //div/following-sibling::a | div + a | | **描述** | 選擇緊接在 \ 元素之後的所有 \

元素。 | | Xpath可以定位當前節點前面的鄰居節點,CSS Selector不能 ```python //*element/preceding-sibling::element ``` ## 父元素、祖先元素定位 CSS Selector是前向的,不能利用子節點定位父節點 | 方法 | 描述 | | -------- | ------------------------------------------------------------ | | .. | 一個點”.“表示選取當前節點,兩個點”..“表示選取當前節點的父節點。 | | ancestor | 當前節點祖先元素(父、祖父...) | | parent | 當前節點的父節點 | ## Id定位 | | **Xpath** | **CSS Selector** | | -------- | --------------------------- | ---------------- | | **語法** | //*\*[@id='example']* | *#example* | | **示例** | //*\*[@id='uesrname']* | #*uesrname* | | **描述** | 選擇*id='uesrname'的*元素。 | | ## Class定位 | | **Xpath** | **CSS Selector** | | -------- | ------------------------------ | ---------------- | | **語法** | //*\*[@class='example']* | *.example* | | **示例** | //*\*[@class='uesrname']* | .*uesrname* | | **描述** | 選擇*class='uesrname'的*元素。 | | ## 屬性值定位 沒有Id和Class的情況下,可以使用其它屬性值定位,比如name、type等。 | | **Xpath** | **CSS Selector** | | -------- | ----------------------------------- | ----------------- | | **語法** | //*\*[@attribute='value']* | [attribute=value] | | **示例** | //*\*[@name='uesrname']* | [name='username'] | | **描述** | 選擇屬性值*name='uesrname'的*元素。 | | xpath可以使用 ‘and’ 或者 ‘or’ 連線兩個屬性: XPATH: ```python //input[@name='login'and @type='submit'] ``` CSS Selector: ```python input[name='login'][type='submit'] ``` CSS Selector可以進行子字串匹配進行定位: ^= 匹配字首 ```python [id^='id_prefix_'] # id字首為‘id_prefix_’的元素 ``` $= 匹配字尾 ```python [id$='_id_sufix'] # id字尾為‘_id_sufix’的元素 ``` *= 包含某個字串 ```python [id*='id_pattern'] # id包含‘id_pattern’的元素 ``` ## Xpath Contains()方法 Contains()方法也許通過部分文字來定位查詢元素,CSS Selector不支援這種用法。 ```python Xpath = //*[contains(@type,'partial_text')] Xpath = //*[contains(@name,'partial_text')] Xpath = //*[contains(@class,'partial_text')] Xpath = //*[contains(@id,'partial_text')] Xpath = //*[contains(text(),'partial_text')] Xpath = //*[contains(@href,'partial_text')] ``` ## Xpath Starts-with()方法 查詢屬性值以特定文字開始的元素 ```python Xpath = //*[starts-with(@type,'start_text')] Xpath = //*[starts-with(@name,'start_text')] Xpath = //*[starts-with(@class,'start_text')] Xpath = //*[starts-with(@id,'start_text')] Xpath = //*[starts-with(text(),'start_text')] Xpath = //*[starts-with(@href,'start_text')] ``` ## Xpath Text()方法 Text()方法基於web元素文字來進行定位 ```python Xpath = //*[text()='text_value'] ``` # 例項 ## 子孫元素定位 百度一下”text“,點選”**資訊**“ ![](https://img2020.cnblogs.com/blog/2229336/202012/2229336-20201220124710113-1738958574.png) Xpath: ```python //*[@id="s_tab"]/descendant::a[1] //*[@id="s_tab"]/child::*[1]/a[1] ``` CSS selector: ```python #s_tab a:nth-child(2) #s_tab a:nth-last-child(9) ``` python測試程式碼: ```python def test_css(self):     self.driver.get("https://www.baidu.com/")     self.driver.find_element_by_id("kw").send_keys("test")            self.driver.find_element_by_id("su").click()            # element = self.driver.find_element_by_css_selector("#s_tab a:nth-child(2)")     # element = self.driver.find_element_by_css_selector('#s_tab a:nth-last-child(9)')     element = self.driver.find_element_by_xpath('//*[@id="s_tab"]/descendant::a[1]')            element.click()     sleep(2) ``` ## 鄰居節點定位 點選”**資訊**“下一個鄰居節點”**視訊**“ xpath ```python //*[@id="s_tab"]/descendant::a[1]/following-sibling::a[1] //*[@id="s_tab"]/child::*[1]/a[1]/following-sibling::a[1] ``` CSS selector: ```python #s_tab a:nth-child(2) + a #s_tab a:nth-last-child(9) + a ``` python測試程式碼: ```python def test_css2(self): self.driver.get("https://www.baidu.com/") self.driver.find_element_by_id("kw").send_keys("test") self.driver.find_element_by_id("su").click() # element = self.driver.find_element_by_css_selector('#s_tab a:nth-child(2) + a') element = self.driver.find_element_by_xpath('//*@id="s_tab"]/descendant::a[1]/following-sibling::a[1]') element.click() sleep(2) ``` ## Xpath Contains()、Starts-with()、Text()定位 測試頁面:http://sahitest.com/demo/linkTest.htm 點選”[linkByContent](http://sahitest.com/demo/linkByContent.htm)“ ![](https://img2020.cnblogs.com/blog/2229336/202012/2229336-20201220124726150-1410131405.png) xpath語法: ```python //*[contains(@href,"Content")] //*[starts-with(@href,"linkByC")] //*[contains(text(),"Content")] //*[text()="linkByContent"] ``` python測試程式碼: ```python def test_css2(self):     self.driver.get("http://sahitest.com/demo/linkTest.htm")     # element = self.driver.find_element_by_xpath('//*[contains(@href,"Content")]')     # element = self.driver.find_element_by_xpath('//*[starts-with(@href,"linkByC")]')     # element = self.driver.find_element_by_xpath('//*[contains(text(),"Content")]')     element = self.driver.find_element_by_xpath('//*[text()="linkByContent"]')     element.click() ``` # 總結 Xpath幾乎可以定位到所以Web元素,CSS Selector效率更高,且程式碼簡潔,但有些元素可能無法定位,特別是需要通過子元素來定位的父元素,或者需要通過文字定位的元素。 在實際使用中,按照自己的實際情況來選擇即可,CSS Selector理論上執行效率更高,但他們的效能差異不是很大,在幾毫秒或者幾十毫秒級別。這兩種定位方法除了本文介紹的以外,還有更多其它高階語法,可以參考官方文件。

--THE END--
> 文章標題:Web自動化測試:xpath & CSS Selector定位 > 本文作者:hiyo > 本文連結:[https://hiyong.gitee.io/posts/selenium-xpath-and-CSS-Selector-locator/](https://hiyong.gitee.io/posts/selenium-xpath-and-CSS-Selector-locator/) > 歡迎關注公眾號:「測試開發小記」及時接收最新技術文章!