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

北京-宏哥發表於2024-11-07

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("name@example.com").fill("playwright@microsoft.com")
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 進行元素定位的一些比較常用的定位方法的理論基礎知識以及在什麼情況下推薦使用,當然了這不是一成不變的,希望大家在使用中可以靈活的應用。

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

相關文章