XPath和CssSelector定位總結



本文鏈接: https://www.cnblogs.com/hchengmx/p/10755116.html

1. 介紹XPath和CssSelector

XPath: XPath 最初是用來在 XML 文檔中定位 DOM 節點的語言,由於 HTML 也可以算作 XML 的一種實現,所以 Selenium 也可以利用 XPath 這一強大的語言來定位 Web 元素。XPath 在傳統屬性定位之外擴展了諸如“定位第三個多選框”等定位能力,以便應對沒有 ID 或 name 屬性的情況。

CSS (Cascading Style Sheets) 是一種用於渲染 HTML 或者 XML 文檔的語言,CSS 利用其選擇器可以將樣式屬性綁定到文檔中的指定元素,即前端開發人員可以利用 CSS 設定頁面上每一個元素的樣式。所以理論上說無論一個元素定位有多復雜,既然開發人員能夠定位到並設置樣式,那么測試人員同樣應該也能定位繼而操作該元素。
多個 CSS 選擇器還可以用逗號拼接為一個組合選擇器,滿足任意其中一個選擇器的元素都會被該組合選擇器選中,逗號的前后允許出現空白。

所以 從工作機制來講:XPath使用路徑標記在XML文檔層次結構中進行導航,簡單說就是遍歷文檔路徑。Selector則是一種匹配模式,速度上優化於XPath。

2. XPath有哪些方式

2.1. 通過XPath語法

XPath = //tagname[@attribute='value']
  • // 目前的節點
  • tagname:想要選的節點的tag,input,div,img等, 但也經常被替換為*
  • Attribute: 想要選擇節點的屬性
  • Value: 屬性的值

用XPath選擇的其他例子:

Xpath=//input[@type='text']				
Xpath=	//label[@id='message23']
Xpath=	//input[@value='RESET']
Xpath=//*[@class='barone']
Xpath=//a[@href='http://demo.guru99.com/']
Xpath= //img[@src='//cdn.guru99.com/images/home/java.png']

補充知識點2: 如何用XPath獲取該元素的父親:

public static IWebElement GetParent(this IWebElement element)
{
    return element.FindElement(By.XPath(".."));
}

2.2. Contains關鍵字

適用於某個屬性動態的值變化, 但是其值總是包含什么特定的字符串。

//*[contains(@id,'message')]

2.3. Start-With

可以理解為contains的延申, 選擇某元素的值總是以XXX開頭

Xpath=//label[starts-with(@id,'message')]

2.4. Or和And關鍵字

用Or的話, 兩個條件其中之一為真則為真, 用And的話, 兩個條件均為真則真(個人用And多一點, 用來篩選元素)。

Xpath=//input[@type='submit' and @name='btnLogin']

2.5. Text()

適用於其內的text在頁面唯一的情況, 書寫起來也最簡單;

XPath-Text()示例

2.6. 軸方法

軸名稱 結果
ancestor 選取當前節點的所有先輩(父、祖父等)。
ancestor-or-self 選取當前節點的所有先輩(父、祖父等)以及當前節點本身。
attribute 選取當前節點的所有屬性。
child 選取當前節點的所有子元素。
descendant 選取當前節點的所有后代元素(子、孫等)。
descendant-or-self 選取當前節點的所有后代元素(子、孫等)以及當前節點本身。
following 選取文檔中當前節點的結束標簽之后的所有節點。
namespace 選取當前節點的所有命名空間節點。
parent 選取當前節點的父節點。
preceding 選取文檔中當前節點的開始標簽之前的所有節點。
preceding-sibling 選取當前節點之前的所有同級節點。
self 選取當前節點。

eg:

Xpath=//*[@type='text']//following::input
Xpath=//*[@id='java_technologies']//child::li
Xpath=//*[text()='Enterprise Testing']//ancestor::div
Xpath=//*[@id='rt-feature']//parent::div

2.7. 補充知識點

2.7.1. 絕對路徑和相對路徑的區別

絕對路徑:以單斜杠 / 開頭, 表示選擇當前節點, 一般從根節點來選取元素, 通過這樣的XPath表達式特別長:

html/body/div[3]/div/div[2]

用絕對路徑選擇元素

相對路徑:以雙斜杠 // 開頭,可以選擇頁面上的任何元素
用相對路徑選擇元素

2.7.2. XPath在不同瀏覽器上的區別

以下來自selenium官方文檔, 原文可以看這里

從原理上來講, 每個瀏覽器都應該有自己的原生xpath方法,要是沒有的話,才會用selenium提供的方法。
具體區別如下:

Driver Tag and Attribute Name Native XPath Support
HtmlUnit Driver Lower-cased Yes
Internet Explorer Driver Lower-cased No
Firefox Driver Case insensitive Yes

下面是一個例子:

<input type="text" name="example" />
<INPUT type="text" name="other" />

用代碼

List<WebElement> inputs = driver.findElements(By.xpath("//input"));

用幾個driver分別會找到下面幾個元素

XPath expression HtmlUnit Driver Firefox Driver(同chrome) Internet Explorer Driver
//input 1 (“example”) 2 2
//INPUT 0 2 0

3. CssSelector有哪些方式

3.1 類選擇器

語法: tag.class

eg:

div.ibm-alternate-rule

3.2 屬性選擇器

語法: css=tag[attribute=value], 更多包括通配符的例子可以看這里

eg:

ul[role='tablist']

3.3 后代選擇器

詳細介紹可以看這里

語法:

tag1 tag2   //tag1的所有后代中的tag為tag2的

eg:

div.sidebar a //結合類選擇器使用, 找到屬性為div且class為sidebar的所有tag為a的后代

3.4 子元素選擇器

詳細介紹可以看這里

語義: 如果您不希望選擇任意的后代元素,而是希望縮小范圍,只選擇某個元素的子元素,請使用子元素選擇器

eg:

table.company td > p

上面的選擇器會選擇作為 td 元素子元素的所有 p 元素,這個 td 元素本身從 table 元素繼承,該 table 元素有一個包含 company 的 class 屬性。

3.4 偽類選擇器

動態偽類: 未被訪問/已被訪問/活動/獲得焦點
UI元素狀態偽類: 第n個孩子;
CSS3的:nth選擇器: element 狀態(禁用/啟用/被選中)

可以在這里 查看詳情。

4. XPath和CssSelector的選擇

根據Microsoft的推薦: 也是推薦CssSelector, 理由如下:

  1. Xpath在不同瀏覽器中會不同(Xpath engines are different in each browser)
  2. Xpath比較難閱讀(XPath can become complex and therefore more difficult to read)
  3. Css selector更快(CSS selectors are faster)
  4. Css是一種基於JQuery的定位策略(CSS is JQuery's locating strategy)
  5. IE沒有Xpath引擎(Internet Explorer does not have a native XPath engine)

CssSelector的劣勢:

  1. 無法找到某元素的父親元素(當然這種也很難遇到)

所以個人定位經驗總結:

  1. 首先考慮這個元素有無唯一的屬性, 比如id/name;
  2. 查看改元素有無唯一的text, 用CssSelector的text()定位;
  3. 這個元素是否為多個屬性, 多個屬性用And連接起來是否可能唯一, 用CssSelector的And關鍵字;
  4. 首選從這個元素的父親元素/祖宗元素, 有無唯一屬性, 善用CssSelector的后代選擇器和子元素選擇器;
  5. 使用約束, 用findelements(By.CssSelector("")).first(ele => ele.Text == "");
  6. 再復雜的我目前還沒見過;

5. 定位的一些優化方法

  1. 盡可能的不要用findelements
List<IWebElement> elements = driver.findelements(By.CssSelector(""));
element = elements.first()
  1. 盡量減少和服務的通信:
if(driver.findelements(By.CssSelector("li[role='radio']").Count() != 0)
{
    driver.findelement(By.CssSelector("li[role='radio']")).click();
}

上面需要和driver通信兩次, 查找元素兩次, 可以考慮替換為下面的代碼。

var element = driver.findelement(By.CssSelector("li[role='radio']"))
if(element!=null)
{
    element.click();
}

6. 參考資料

  1. XPath in Selenium WebDriver: Complete Tutorial
  2. 全球化測試中利用 Selenium 定位 Web 元素難點解析
  3. 記一次元素定位優化行動
  4. XPath 語法
  5. XPath 節點
  6. XPath Axes(軸)
  7. selenium官方關於xpath的介紹
  8. 一招讓 IOS 自動化化快的飛起
    9/ portaldocs/top-extensions-csharp-test-framework.md at master · Azure/portaldocs · GitHub


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM