[譯] 用 CSS 選擇器和自定義屬性來升級你的項目

用 CSS 選擇器和自定義屬性來升級你的項目

這篇文章原文刊登在 TestProject。感謝大家的支持,讓 SitePoint 成爲可能。css

Selenium WebDriver 的元素選擇器是 自動化測試框架 中所說起的核心組件中的一種,同時也是與 web 應用進行交互的關鍵。在對 自動化元素選擇器 的回顧中, 咱們討論了不少不一樣的選擇器應用策略,探究其功能,權衡優缺點,最終咱們推薦 最佳的選擇器應用策略 —— 帶有自定義屬性的 CSS 選擇器。前端

Selenium 的元素選擇器

選擇最好的 元素選擇器 策略是成功的關鍵,也減輕了自動化工做的維護壓力。所以,作出選擇的時候應該從使用難度,多功能性,是否具備在線支持,文檔豐富程度以及性能等多方面進行考慮。前期的充分考慮是有回報的,自動化工做會更容易維護。node

就像從技術方面考慮元素選擇器同樣,也要考慮到團隊文化。在自動化工做中採用元素選擇器時,在開發者與 QA 之間成熟的合做文化能夠解鎖更高成就,取得更好的效果。夯實軟件開發週期中其它方面的合做基礎不只對自動化工做有益,更是對團隊有益。python

全部的代碼示例都是由 PythonSelenium WebDriver 中的命令編寫而成,但也廣泛適用於其它編程語言和框架。android

HTML 代碼示例:

在每一段的示例中,都是使用如下導航菜單的 HTML 片斷代碼:ios

<div id="main-menu">
  <div class="menu"><a href="/home">Home</a></div>
  <div class="menu"><a href="/shop">Shop</a>
    <div class="submenu">
      <a href="/shop/gizmo">Gizmo</a>
      <a href="/shop/widget">Widget</a>
      <a href="/shop/sprocket">Sprocket</a>
    </div>
  </div>
</div>
複製代碼

糟糕的選擇器: 標籤名,連接文本,部分連接文本和 name 屬性選擇器

關於這部份內容不須要花太多時間來說,由於這些選擇器的使用場景都頗有限。在整個自動化框架中普遍使用這些選擇器不是一個好選擇。它們所完成的需求徹底能夠經過其它元素選擇器策略輕鬆實現。只有在特定需求中須要去處理特殊案例的時候才使用這幾種選擇器。即便如此,大多數特殊場景並無特殊到非要使用這幾種選擇器才能解決。你能夠在沒有其餘選擇器選項可用(例如自定義標籤或 id)的狀況下使用。git

舉個栗子:

使用標籤名稱選擇器,會選擇到很是多的匹配到標籤名稱的元素。它的用途很是有限,只能做爲在須要選擇大量相同類型的元素的惟一狀況下的解決方案。下面這個例子會返回示例 HTML 代碼中所有 4 個 div 元素。github

driver.find_elements(By.TAG_NAME, "div")
複製代碼

也能夠像下面的例子這樣經過連接來選擇。如你所見,這樣只能定位到錨點標籤並且只能定位這些錨點標籤的文本:web

driver.find_elements(By.LINK_TEXT, "Home")
driver.find_elements(By.PARTIAL_LINK_TEXT, "Sprock")
複製代碼

最後,也能夠經過 name 屬性來選擇元素,可是在 HTML 代碼示例中能夠看出,那些標籤是沒有 name 屬性的。這在絕大多數應用中都是一個常見問題,由於給每一個 HTML 屬性中添加一個 name 屬性不是常規的代碼實踐。假如主菜單元素像下面同樣有一個 name 屬性:chrome

<div id="main-menu" name="menu"></div>
複製代碼

能夠像這樣匹配到這個元素:

driver.find_elements(By.NAME, "menu")
複製代碼

如你所見,以上這些元素選擇策略的使用場景都頗有限。下面的方法都會更好一些,它們更靈活多變。

總結: 標籤名,連接文本,部分連接文本和 name 屬性選擇器

優勢 缺點
使用簡單 不夠靈活
使用場景極其有限
在某些場景甚至可能用不了

還不錯的選擇器: XPath

XPath 是一種靈活多變的選擇器策略。這是我我的很喜歡的。XPath 能夠選擇頁面中的任意元素,不管它有沒有 class 和 id (雖然沒有 class 和 id 的話很難維護)。該選項很是靈活有用,由於你能夠選擇 父元素。XPath也有許多內置的功能,可讓你自定義元素選擇。

可是,多功能性也帶來了複雜性。鑑於 XPath 能夠作這麼多事,相比於其它選擇器,它的學習曲線也更陡峭。這一不足是能夠被它很是讚的在線文檔抵消的。在 W3Schools.com 上找到的 XPath 入門指南 是一個很不錯的資源。

還應該指出,使用 XPath 的時候有一件事須要進行權衡。雖然能夠經過 XPath 選擇父元素並使用一系列內置函數,可是 XPath 在 IE 瀏覽器的表現不佳。在選擇元素選擇器策略時,應該考慮這個問題。若是你有選擇父元素的須要的話,要考慮它對 IE 上進行的 跨瀏覽器 測試的影響。本質上,在 IE 中運行自動化測試的耗時更長。若是你的用戶羣體的 IE 使用率不高的話,考慮到在 IE 上跑測試的時候更少,XPath 依然是一個好選擇。若是你的用戶基本上都是 IE 重度使用者的話,XPath 就只能做爲沒有其它更好方式時的備胎選擇了。

舉個栗子:

若是你有需求要選擇父元素,那就必須採用 XPath。下面是作法,依然使用咱們的示例,假設你要定位一個基於錨點元素的主菜單元素的父元素:

driver.find_elements(By.XPATH, "//a[id=menu]/../")
複製代碼

這個元素選擇器會定位到第一個 id 等於 "menu" 的錨點標籤,而後經過 「/../」 定位到它的父元素。最終結果就是你會定位到主菜單元素。

總結: XPath

優勢 缺點
能夠定位到父元素 IE 上表現欠佳
很是靈活 陡峭的學習曲線
很是多的在線支持

超級棒的元素選擇器: ID 和 Class

ID 和 Class 元素選擇器在自動化中是兩個不一樣的選項,會在應用程序中執行不一樣的功能。然而做爲自動化工做的選擇器策略,這兩種選擇器的區別很小,咱們不必將它們分開考慮。在應用程序中,UI 界面開發者能夠操做和給定義了 "id" 和 "class" 屬性的元素設置樣式。對於自動化工做來講,咱們使用它們來針對特定元素進行交互。

使用 ID 和 Class 原則器的一大好處是它們受應用程序結構變化的影響最小。假設,你要建立一個鏈式地依賴於一些元素和 子元素 的 XPath 或 CSS 選擇器,若是此時有一個功能須要增長一些新元素從而中斷了這個鏈條,會發生什麼?使用 ID 和 Class 元素選擇器,您能夠定位特定的元素,而不是依賴頁面結構。同時也沒有過於寬鬆易變。應該經過給特定元素的位置建立測試用例來自動檢測改動。改動不該該毀壞你的整個自動化套件。可是,若是開發者直接對自動化中使用的 ID 或 Class 進行更改的話,仍是會影響到你的測試。

又或者若是 HTML 標籤沒有自動化程序中可以使用的 ID 和 Class 屬性的話,這種策略就沒法使用。若是 HTML 標籤沒有自動化程序中可以使用的 ID 和 Class 屬性的話,這種方法就很難使用。

舉個栗子:

在示例中,若是咱們想選擇到頂級的菜單元素,那應該是這樣的:

driver.find_elements(By.ID, "main-menu")
複製代碼

若是要選擇第一個菜單項,則是這樣:

driver.find_elements(By.CLASS_NAME, "menu")
複製代碼

總結: ID 和 Class 選擇器

優勢 缺點
易於維護 開發人員可能會直接修改它們,自動化工做就沒法進行了
學習難度低
受頁面結構的影響最小

最佳的元素選擇器: 具備自定義屬性的 CSS 選擇器

若是大家的 QA 團隊與開發部門合做良好的話,大家頗有可能會選擇這種最佳實踐方法應用到自動化工做中。使用自定義屬性和 CSS 選擇器來定位元素對於 QA 團隊和整個組織來講都有不少好處。對於 QA 團隊來講,這可讓自動化工程師直接定位到特定元素,無需建立複雜的元素原則器。可是,這須要在應用程序中添加自動化團隊所需的屬性。爲了充分發揮最佳實踐的優點,開發部門和 QA 團隊應共同實施這一策略。

我想簡短地提示一下,CSS 選擇器方法並不依賴於自定義屬性。CSS 選擇器能夠像 XPath 同樣定位到 HTML 文檔流中的任意標籤和屬性。

如今咱們來看這個方法須要咱們作什麼。爲了能最好地執行這一策略,大家的自動化團隊瞭解本身在自動化工做中想要定位什麼。在與開發人員的合做中,最有多是與前端工程師的合做中,QA 團隊須要制定一個自定義屬性的應用模式,放到團隊所須要鏈接合做的每個目標中。對於這個例子來講,咱們把 "tid" 屬性附加到了目標元素上。

這裏須要強調的一個技術上的注意事項是 CSS 選擇器的限制。CSS 選擇器是不容許像 XPath 同樣選擇父元素的。這是爲了不頁面上 CSS 樣式的無限循環。這對網頁設計來講是件好事,可是,當它做爲自動化的元素選擇器時是一種限制。幸運的是,這種限制能夠由開發實現自定義屬性來避免。QA 應請求合適的自定義屬性,以便無需選擇父元素。

若是大家公司的開發部門和 QA 團隊不存在合做文化的話,也不用擔憂!應該實施這個策略,由於它是能夠推進合做的途徑。不管這種合做文化是否存在,你也應該先採用這種方式而後看看效果怎麼樣。你不但會擁有一個易於維護的選擇器策略,你還會看到遍佈整個公司的協做文化所帶來的便利。這種合做關係會在質量保障的多個方面受益,好比減小缺陷,縮短上市時間並提升生產力。

爲了更好地實行這個策略並建立合做關係,QA 團隊應該從一開始就參與到設計過程當中,與開發部門合做並 review 需求。隨着開發部門設計功能,QA 應該建議哪裏能夠實現自定義屬性的位置,以最好地支持自動化工做。經過在設計階段初期就鼓勵這種合做,可以讓 QA 團隊和開發部門會在合做關係中走得更近,提升開發效率。這也可能會對軟件開發週期的其它領域產生溢出效應。在鼓勵開發部門與 QA 團隊的合做中,他們彼此更將熟悉,一樣的,這種關係也會映射到其它領域的合做中。

舉個栗子:

在示例 HTML 代碼中的錨點元素上使用自定義屬性:

<div id="main-menu">
  <div class="menu"><a tid="home-link" href="/home">Home</a></div>
  <div class="menu"><a tid="shop-link" href="/shop">Shop</a>
    <div class="submenu">
      <a tid="gizmo-link" href="/shop/gizmo">Gizmo</a>
      <a tid="widget-link" href="/shop/widget">Widget</a>
      <a tid="sprocket-link" href="/shop/sprocket">Sprocket</a>
    </div>
  </div>
</div>
複製代碼

注意,一些元素上有了新屬性。咱們建立了一個叫 "tid" 的新屬性,與標準的 HTML 屬性並沒有任何充衝突。有了自定義屬性,咱們能夠經過一個 CSS 元素選擇器去定位它:

driver.find_element(By. CSS_SELECTOR, "[tid=home-link]")
複製代碼

假設,你想選擇菜單中全部的連接,不管一級菜單仍是二級菜單。你能夠經過 CSS 選擇器,建立靈活多變的元素選擇器組:

driver.find_element(By.CSS_SELECTOR, "#main-menu [tid*='-link']")
複製代碼

"*=" 作的是,在全部元素的 "tid" 字段中由通配符搜索 "-link"。把它放到 "#main-menu" ID 選擇符的後面,它就只搜索主菜單內的元素了。

若是你想脫離自定義屬性來使用這個策略,也依然是正確路線。舉例說,你能夠經過以下方式定位到 Shop 的子菜單中的連接:

driver.find_element(By. CSS_SELECTOR, "#main-menu .submenu a")
複製代碼

這一策略可使得工程師建立易於維護且不受 UI 界面中無關變化影響的自動化工做。選擇這一策略是最好的方法。這不只是一個易於維護的自動化解決方案,並且還會鼓勵 QA 團隊和開發人員之間的合做。

總結:具備自定義屬性的 CSS 選擇器

優勢 缺點
學習難度低 初始階段就涉及到與開發人員合做
豐富的在線支持
靈活多變
超級棒的兼容性

結論

在自動化框架中實現企業標準級的元素選擇器策略有一些很好的選擇。應該避免選擇像是標籤名或連接文本選擇器,除非它們是你惟一的選擇。XPath,ID 和 Class 選擇器則是一個好路線。到目前爲止,最好的方法是實現自定義屬性並用 CSS 選擇器來定位。這也鼓勵了開發部門與 QA 團隊之間的合做。

這是全部選項的比較表:

1511434384(1).jpg


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索