《最新出爐》系列初窺篇-Python+Playwright自動化測試-5-元素定位大法-上篇

2023-06-30 18:01:25

1.簡介

說到元素定位,小夥伴或者童鞋們肯定會首先想到 selenium 的八大元素定位大法。同理Playwright也有自己的元素定位的方法。今天就給小夥伴或者童鞋們講解和分享一下Playwright的元素定位方法。

宏哥對UI自動化的理解:定位元素--->操作元素---->斷言。

2.定位器

定位器(Locator)是 Playwright 的自動等待和重試能力的核心部分。定位器是一種隨時在網頁上查詢元素的方法,用於在元素上執行諸如 .click、.fill 之類的操作。可以使用 page.locator(selector, **kwargs) 方法建立自定義定位器。

選擇器(Selector)是用於建立定位器的字串。Playwright 支援許多不同的選擇器,比如 Text、CSS、XPath 等。閱讀 in-depth guide 檔案,瞭解更多關於可用的選擇器以及如何進行選擇的資訊。

3.內建定位器

這些是 playwright 推薦的內建定位器。

  • page.get_by_role()通過顯式和隱式可存取性屬性進行定位。
  • page.get_by_text()通過文字內容定位。
  • page.get_by_label()通過關聯標籤的文字定位表單控制元件。
  • page.get_by_placeholder()按預留位置定位輸入。
  • page.get_by_alt_text()通過替代文字定位元素,通常是影象。
  • page.get_by_title()通過標題屬性定位元素。
  • page.get_by_test_id()根據data-testid屬性定位元素(可以設定其他屬性)。

當然除了這些,還有其他定位方法,selenium的8種by元素定位,id、xpath、css等都可使用,還有W3C標準規定的webDriver協定為5種定位方式CSS、Link text、Partial link text、Tag name、XPath

playwright把這些定位歸類成3種,分別是:css、xpath、text。

如:

page.locator("xpath=//h2")
page.locator("text=文字輸入") 
page.locator("#s-usersetting-top")
page.locator("input[name=\"wd\"]").click()
page.get_by_role("button", name="百度一下").click()
page2.get_by_placeholder("唱片名、表演者、條碼、ISRC").click()
page2.get_by_text("或者,親自來幫豆瓣新增:").click()

官方檔案給出一個登入系統的使用範例如下:

page.get_by_label("User Name").fill("John")

page.get_by_label("Password").fill("secret-password")

page.get_by_role("button", name="Sign in").click()

expect(page.get_by_text("Welcome, John!")).to_be_visible()

3.1角色定位-page.get_by_role()

Playwright帶有多個內建定位器。為了使測試具有彈性,我們建議優先考慮面向使用者的屬性和顯式協定,例如page.get_by_role()。例如:以下 DOM 結構。

button通過名稱為「登入」的角色定位元素。

page.get_by_role("button", name="Sign in").click()

每次將定位器用於操作時,都會在頁面中找到一個最新的 DOM 元素。在下面的程式碼片段中,底層 DOM 元素將被定位兩次,一次在每個動作之前。這意味著如果 DOM 由於重新渲染而在呼叫之間發生變化,則將使用與定位器對應的新元素。

locator = page.get_by_role("button", name="Sign in")

locator.hover()
locator.click()

請注意,所有建立定位器的方法(例如page.get_by_label() )也可用於Locator和FrameLocator類,因此您可以將它們連結起來並迭代地縮小定位器的範圍。

locator = page.frame_locator("my-frame").get_by_role("button", name="Sign in")

locator.click()

page.get_by_role ()定位器反映了使用者和輔助技術如何感知頁面,例如某個元素是按鈕還是核取方塊。按角色定位時,通常還應傳遞可存取的名稱,以便定位器準確定位元素。

例如,考慮以下 DOM 結構。

 您可以通過其隱式角色定位每個元素:

expect(page.get_by_role("heading", name="Sign up")).to_be_visible()

page.get_by_role("checkbox", name="Subscribe").check()

page.get_by_role("button", name=re.compile("submit", re.IGNORECASE)).click()

角色定位器包括按鈕、核取方塊、標題、連結、列表、表格等,並遵循ARIA 角色、ARIA 屬性和可存取名稱的 W3C 規範。

請注意:許多html元素如:<button>都有一個隱式定義的角色,該角色可被角色定位器識別。

請注意,角色定位器不會取代可存取性稽核和一致性測試,而是提供有關 ARIA 指南的早期反饋。

3.1.1何時使用角色定位器

我們建議優先使用角色定位器來定位元素,因為這是最接近使用者和輔助技術感知頁面的方式。

3.2標籤定位-page.get_by_label()

大多數表單控制元件通常都有專用標籤,可以方便地用於與表單互動。在這種情況下,您可以使用page.get_by_label()通過其關聯標籤定位控制元件。例如:以下 DOM 結構。

您可以在通過標籤文字定位後填寫輸入:

page.get_by_label("Password").fill("secret")
3.2.1何時使用標籤定位器

定位表單區域時,使用標籤定位器。

3.3預留位置定位-page.get_by_placeholder()

輸入可能具有預留位置屬性,以向用戶提示應輸入的值。您可以使用page.get_by_placeholder()定位此類輸入。例如:以下 DOM 結構。

 您可以在通過預留位置文字定位後填充輸入:

page.get_by_placeholder("[email protected]").fill("[email protected]")
3.3.1何時使用預留位置定位器

在定位沒有標籤但具有預留位置文字的表單元素時,使用此定位器。

3.4文字定位-page.get_by_text()

根據元素包含的文字查詢元素。使用page.get_by_text()時,您可以通過子字串、精確字串或正規表示式進行匹配。例如:以下 DOM 結構。

 您可以通過元素包含的文字來查詢該元素:

expect(page.get_by_text("Welcome, John")).to_be_visible()

設定完全匹配:

expect(page.get_by_text("Welcome, John", exact=True)).to_be_visible()

與正規表示式匹配:

expect(page
    .get_by_text(re.compile("welcome, john", re.IGNORECASE)))
    .to_be_visible()
注意:按文字匹配始終規範化空格,即使完全匹配也是如此。例如,它將多個空格轉換為一個空格,將換行符轉換為空格,並忽略前導和尾隨空格。
3.4.1何時使用文字定位器

建議使用文字定位器來查詢非互動式元素,如div, span, p 等。對於互動式元素,如請button, a, input, 使用角色定位器。

您還可以按文字進行篩選,這在嘗試在列表中定位特定專案時很有用。

3.5替代文字定位-page.get_by_alt_text()

所有影象都應該有一個alt描述影象的屬性。您可以使用page.get_by_alt_text()根據替代文字定點陣影象。例如:以下 DOM 結構。

 可以在通過替代文字選項找到影象後單擊它:

page.get_by_alt_text("playwright logo").click()
3.5.1何時使用替代文字定位器
當您的元素支援替代文字(例如img和area元素)時使用此定位器。

3.6標題定位-page.get_by_title()

使用page.get_by_title()找到具有匹配 title 屬性的元素。例如:以下 DOM 結構。

 您可以在通過標題文字找到它後檢查問題數:

expect(page.get_by_title("Issues count")).to_have_text("25 issues")
3.6.1何時使用標題定位器

當您的元素具有該title屬性時使用此定位器。

3.7測試id定位-page.get_by_test_id()

通過測試 ID 進行測試是最具彈性的測試方式,因為即使您的文字或屬性角色發生變化,測試仍會通過。QA 和開發人員應該定義明確的測試 ID 並使用page.get_by_test_id()查詢它們。但是,通過測試 ID 進行的測試不是面向使用者的。如果角色或文字值對您很重要,那麼請考慮使用面向使用者的定位器,例如角色定位器和文字定位器。例如:以下 DOM 結構。

 您可以通過它的測試 ID 定位到該元素:

page.get_by_test_id("directions").click()
3.7.1何時使用測試id定位器

當你選擇使用測試id的方法,或者角色、文字無法定位時,你也可以使用測試id進行定位。

3.7.2設定自定義測試id屬性

預設情況下,page.get_by_test_id()將根據data-testid屬性定位元素,但您可以在測試設定中或通過呼叫selectors.set_test_id_attribute()對其進行設定。

設定測試 ID 以使用自定義資料屬性進行測試。

playwright.selectors.set_test_id_attribute("data-pw")

在您的 html 中,您現在可以使用data-pwtest id 而不是 default data-testid。

 然後像往常一樣定位元素:

page.get_by_test_id("directions").click()

4.CSS或Xpath定位

如果必須使用 CSS 或 XPath 定位器,則可以使用 page.locator()建立一個定位器,該定位器採用描述如何在頁面中定位元素的選擇器。Playwright 支援 CSS 和 XPath 選擇器,並在省略字首css=或xpath=時自動檢測它們。它會自動判斷你寫的是css還是xpath語法,前提是你語法沒有錯誤。

page.locator("css=button").click()
page.locator("xpath=//button").click()

page.locator("button").click()
page.locator("//button").click()

XPath 和 CSS 選擇器可以繫結到 DOM 結構或實現。當 DOM 結構更改時,這些選擇器可能會中斷。下面的長 CSS 或 XPath 鏈是導致測試不穩定的不良做法的範例:

page.locator(
    "#tsf > div:nth-child(2) > div.A8SBwf > div.RNNXgb > div > div.a4bIc > input"
).click()

page.locator('//*[@id="tsf"]/div[2]/div[1]/div[1]/div/div[2]/input').click()

4.1何時使用CSS或Xpath定位器

不建議使用 CSS 和 XPath,因為 DOM 經常會發生變化,從而導致無彈性測試。相反,請嘗試提出一個接近使用者感知頁面的定位器,例如角色定位器,或使用測試 ID 定義顯式測試協定。

5.文字選擇器定位-text()

文字選擇器是一個非常實用的定位方式,根據頁面上看到的text文字就可以定位了,比如我們經常使用xpath 的文字選擇器定位。

  • 完全匹配文字 //*[text()="北京-宏哥"]
  • 包含某個文字 //*[contains(text(),"北京-宏哥")

playwright 封裝了text文字定位的方式,也可以支援2種文字定位方式

page.click("text=北京-宏哥")
page.click("text='北京-宏哥'")

text=北京-宏哥和text='北京-宏哥'的區別:

  • text=北京-宏哥 沒有加引號(單引號或者雙引號),模糊匹配,對大小寫不敏感
  • text='北京-宏哥' 有引號,精確匹配,對大小寫敏感

text文字除了可以定位a標籤,還可以定位 button 按鈕,input標籤的button 按鈕,有value="百度一下" 文字值

<input type=button value="百度一下">

或者是button 標籤的按鈕

<button>百度一下</button>

6.HTML屬性選擇器定位

HTML 屬性選擇器, 根據html元素的id 定位

page.fill("id=kw", "北京-宏哥")

7.select選擇器組合定位

定位目標元素,我們有時候可以使用>>(兩個大於號)連線不同的selector可組合使用,例如:我們定位百度首頁的登入

#id 屬性+ css
page.fill('form >> [name="username"]', "北京-宏哥")
page.fill('form >> #TANGRAM__PSP_11__password', "aa123456")
page.click("text=登入")

form >> [name="username"] 定位方式等價於

#page.fill('form >> [name="username"]', "北京-宏哥")
page.locator("form").locator('[name="username"]').fill("北京-宏哥")

相當於是根據父元素找到子元素了

登入按鈕的值是value="登入 > ",可以用text文字定位的方式,模糊匹配到,這種人性化的設計提高了定位的效率。

<input id="TANGRAM__PSP_11__submit" type="submit" value="登入" class="pass-button pass-button-submit">

8.小結

今天這一篇主要是講解我們日常工作中在使用Playwright進行元素定位的一些比較常用的定位方法的理論基礎知識以及在什麼情況下推薦使用,當然了這不是一成不變的,希望大家在使用中可以靈活的應用。

好了,今天時間也不早了,宏哥就講解和分享到這裡,感謝您耐心的閱讀,希望對您有所幫助。