定位器策略

在 DOM 中識別一個或多個特定元素的方法。

定位器是一種在頁面上識別元素的方式。它是傳遞給尋找元素方法的參數。

查看我們的建議的測試實務,以取得關於定位器的提示,包括何時使用哪種定位器,以及為何要將定位器與尋找方法分開宣告。

傳統定位器

Selenium 在 WebDriver 中提供對這 8 種傳統定位策略的支援

定位器描述
類別名稱定位類別名稱包含搜尋值的元素(不允許複合類別名稱)
CSS 選擇器定位符合 CSS 選擇器的元素
ID定位 ID 屬性符合搜尋值的元素
名稱定位 NAME 屬性符合搜尋值的元素
連結文字定位可見文字符合搜尋值的錨點元素
部分連結文字定位可見文字包含搜尋值的錨點元素。如果有多個元素符合,則只會選取第一個。
標籤名稱定位標籤名稱符合搜尋值的元素
XPath定位符合 XPath 表達式的元素

建立定位器

為了使用 Selenium 操作網頁元素,我們需要先在網頁上找到它。Selenium 提供了上述方法,我們可以藉此在頁面上定位元素。為了理解和建立定位器,我們將使用以下 HTML 片段。

<html>
<body>
<style>
.information {
  background-color: white;
  color: black;
  padding: 10px;
}
</style>
<h2>Contact Selenium</h2>

<form>
  <input type="radio" name="gender" value="m" />Male &nbsp;
  <input type="radio" name="gender" value="f" />Female <br>
  <br>
  <label for="fname">First name:</label><br>
  <input class="information" type="text" id="fname" name="fname" value="Jane"><br><br>
  <label for="lname">Last name:</label><br>
  <input class="information" type="text" id="lname" name="lname" value="Doe"><br><br>
  <label for="newsletter">Newsletter:</label>
  <input type="checkbox" name="newsletter" value="1" /><br><br>
  <input type="submit" value="Submit">
</form> 

<p>To know more about Selenium, visit the official page 
<a href ="www.selenium.dev">Selenium Official Page</a> 
</p>

</body>
</html>

類別名稱

HTML 頁面網頁元素可以具有類別屬性。我們可以在上面顯示的 HTML 片段中看到一個範例。我們可以使用 Selenium 中提供的類別名稱定位器來識別這些元素。

移動程式碼

    WebDriver driver = new ChromeDriver();
	driver.findElement(By.className("information"));
  
    driver = webdriver.Chrome()
    driver.get("https://selenium.dev.org.tw/selenium/web/locators_tests/locators.html")
    element = driver.find_element(By.CLASS_NAME, "information")
    var driver = new ChromeDriver();
	driver.FindElement(By.ClassName("information"));
  
    driver.find_element(class: 'information')
    let driver = await new Builder().forBrowser('chrome').build();
	const loc = await driver.findElement(By.className('information'));
  
    val driver = ChromeDriver()
	val loc: WebElement = driver.findElement(By.className("information"))
  

CSS 選擇器

CSS 是用於樣式化 HTML 頁面的語言。我們可以使用 css 選擇器定位策略來識別頁面上的元素。如果元素具有 id,我們會將定位器建立為 css = #id。否則,我們遵循的格式是 css =[attribute=value]。讓我們看看上面 HTML 片段中的一個範例。我們將使用 css 為名字文字方塊建立定位器。

移動程式碼

    WebDriver driver = new ChromeDriver();
	driver.findElement(By.cssSelector("#fname"));
  
    driver = webdriver.Chrome()
    driver.get("https://selenium.dev.org.tw/selenium/web/locators_tests/locators.html")
    element = driver.find_element(By.CSS_SELECTOR, "#fname")
    var driver = new ChromeDriver();
	driver.FindElement(By.CssSelector("#fname"));
  
    driver.find_element(css: '#fname')
    let driver = await new Builder().forBrowser('chrome').build();
	const loc = await driver.findElement(By.css('#fname'));
  
    val driver = ChromeDriver()
	val loc: WebElement = driver.findElement(By.css("#fname"))
  

ID

我們可以使用網頁中元素的 ID 屬性來定位它。通常,ID 屬性對於網頁上的每個元素都應該是唯一的。我們將使用它來識別姓氏欄位。

移動程式碼

    WebDriver driver = new ChromeDriver();
	driver.findElement(By.id("lname"));
  
    driver = webdriver.Chrome()
    driver.get("https://selenium.dev.org.tw/selenium/web/locators_tests/locators.html")
    element = driver.find_element(By.ID, "lname")
    var driver = new ChromeDriver();
	driver.FindElement(By.Id("lname"));
  
    driver.find_element(id: 'lname')
    let driver = await new Builder().forBrowser('chrome').build();
	const loc = await driver.findElement(By.id('lname'));
  
    val driver = ChromeDriver()
	val loc: WebElement = driver.findElement(By.id("lname"))
  

名稱

我們可以使用網頁中元素的 NAME 屬性來定位它。通常,NAME 屬性對於網頁上的每個元素都應該是唯一的。我們將使用它來識別電子報核取方塊。

移動程式碼

    WebDriver driver = new ChromeDriver();
	driver.findElement(By.name("newsletter"));
  
    driver = webdriver.Chrome()
    driver.get("https://selenium.dev.org.tw/selenium/web/locators_tests/locators.html")
    element = driver.find_element(By.NAME, "newsletter")
    var driver = new ChromeDriver();
	driver.FindElement(By.Name("newsletter"));
  
    driver.find_element(name: 'newsletter')
    let driver = await new Builder().forBrowser('chrome').build();
	const loc = await driver.findElement(By.name('newsletter'));
  
    val driver = ChromeDriver()
	val loc: WebElement = driver.findElement(By.name("newsletter"))
  

如果我們要定位的元素是連結,我們可以使用連結文字定位器在網頁上識別它。連結文字是連結顯示的文字。在共享的 HTML 片段中,我們有一個可用的連結,讓我們看看我們將如何定位它。

移動程式碼

    WebDriver driver = new ChromeDriver();
	driver.findElement(By.linkText("Selenium Official Page"));
  
    driver = webdriver.Chrome()
    driver.get("https://selenium.dev.org.tw/selenium/web/locators_tests/locators.html")
    element = driver.find_element(By.LINK_TEXT, "Selenium Official Page")
    var driver = new ChromeDriver();
	driver.FindElement(By.LinkText("Selenium Official Page"));
  
    driver.find_element(link_text: 'Selenium Official Page')
    let driver = await new Builder().forBrowser('chrome').build();
	const loc = await driver.findElement(By.linkText('Selenium Official Page'));
  
    val driver = ChromeDriver()
	val loc: WebElement = driver.findElement(By.linkText("Selenium Official Page"))
  

如果我們要定位的元素是連結,我們可以使用部分連結文字定位器在網頁上識別它。連結文字是連結顯示的文字。我們可以傳遞部分文字作為值。在共享的 HTML 片段中,我們有一個可用的連結,讓我們看看我們將如何定位它。

移動程式碼

    WebDriver driver = new ChromeDriver();
	driver.findElement(By.partialLinkText("Official Page"));
  
    driver = webdriver.Chrome()
    driver.get("https://selenium.dev.org.tw/selenium/web/locators_tests/locators.html")
    element = driver.find_element(By.PARTIAL_LINK_TEXT, "Official Page")
    var driver = new ChromeDriver();
	driver.FindElement(By.PartialLinkText("Official Page"));
  
    driver.find_element(partial_link_text: 'Official Page')
    let driver = await new Builder().forBrowser('chrome').build();
	const loc = await driver.findElement(By.partialLinkText('Official Page'));
  
    val driver = ChromeDriver()
	val loc: WebElement = driver.findElement(By.partialLinkText("Official Page"))
  

標籤名稱

我們可以使用 HTML 標籤本身作為定位器來識別頁面上的網頁元素。從上面共享的 HTML 片段中,讓我們使用其 html 標籤“a”來識別連結。

移動程式碼

    WebDriver driver = new ChromeDriver();
	driver.findElement(By.tagName("a"));
  
    driver = webdriver.Chrome()
    driver.get("https://selenium.dev.org.tw/selenium/web/locators_tests/locators.html")
    element = driver.find_element(By.TAG_NAME, "a")
    var driver = new ChromeDriver();
	driver.FindElement(By.TagName("a"));
  
    driver.find_element(tag_name: 'a')
    let driver = await new Builder().forBrowser('chrome').build();
	const loc = await driver.findElement(By.tagName('a'));
  
    val driver = ChromeDriver()
	val loc: WebElement = driver.findElement(By.tagName("a"))
  

XPath

HTML 文件可以被視為 XML 文件,然後我們可以使用 xpath,這將是到達感興趣元素的路徑,以定位該元素。XPath 可以是絕對 xpath,它是從文件的根目錄建立的。範例 - /html/form/input[1]。這將傳回男性單選按鈕。或者 xpath 可以是相對的。範例 - //input[@name=‘fname’]。這將傳回名字文字方塊。讓我們使用 xpath 為女性單選按鈕建立定位器。

移動程式碼

    WebDriver driver = new ChromeDriver();
	driver.findElement(By.xpath("//input[@value='f']"));
  
    driver = webdriver.Chrome()
    driver.get("https://selenium.dev.org.tw/selenium/web/locators_tests/locators.html")
    element = driver.find_element(By.XPATH, "//input[@value='f']")
    var driver = new ChromeDriver();
	  driver.FindElement(By.Xpath("//input[@value='f']"));
  
    driver.find_element(xpath: "//input[@value='f']")
    let driver = await new Builder().forBrowser('chrome').build();
	const loc = await driver.findElement(By.xpath('//input[@value='f']'));
  
    import org.openqa.selenium.By
    val driver = ChromeDriver()
	  val loc: WebElement = driver.findElement(By.xpath('//input[@value='f']'))
  

使用定位器

FindElement 讓使用定位器變得輕而易舉!對於大多數語言,您只需要使用 webdriver.common.by.By,但在其他語言中,這就像在 FindElement 函式中設定一個參數一樣簡單

By

移動程式碼

    import org.openqa.selenium.By;
    WebDriver driver = new ChromeDriver();
	driver.findElement(By.className("information"));
  
    from selenium.webdriver.common.by import By
    driver = webdriver.Chrome()
	driver.find_element(By.CLASS_NAME, "information")
  
    var driver = new ChromeDriver();
	driver.FindElement(By.ClassName("information"));
  
    driver.find_element(class: 'information')
    let driver = await new Builder().forBrowser('chrome').build();
	const loc = await driver.findElement(By.className('information'));
  
    import org.openqa.selenium.By
    val driver = ChromeDriver()
	val loc: WebElement = driver.findElement(By.className("information"))
  

ByChained

ByChained 類別讓您可以將兩個 By 定位器鏈結在一起。例如,您不必定位父元素,然後再定位該父元素的子元素,而是可以將這兩個 FindElement() 函式合併為一個。

        By example = new ByChained(By.id("login-form"), By.id("username-field"));
            WebElement username_input = driver.findElement(example);

ByAll

ByAll 類別讓您可以同時使用兩個 By 定位器,尋找符合您任一 By 定位器的元素。例如,您不必使用兩個 FindElement() 函式來分別尋找使用者名稱和密碼輸入欄位,而是可以在一個乾淨的 FindElements() 中一起找到它們

        By example = new ByAll(By.id("password-field"), By.id("username-field"));
            List<WebElement> login_inputs = driver.findElements(example);

相對定位器

Selenium 4 引入了相對定位器(先前稱為友善定位器)。當不容易為所需的元素建構定位器,但很容易在空間上描述元素相對於具有易於建構的定位器的元素的位置時,這些定位器非常有用。

運作方式

Selenium 使用 JavaScript 函式 getBoundingClientRect() 來判斷頁面上元素的大小和位置,並可以使用此資訊來定位鄰近元素。

相對定位器方法可以將先前定位的元素參考或另一個定位器作為原點的參數。在這些範例中,我們將僅使用定位器,但您可以將最終方法中的定位器替換為元素物件,它將以相同的方式運作。

讓我們考慮以下範例,以了解相對定位器。

Relative Locators

可用的相對定位器

上方

如果電子郵件文字欄位元素由於某些原因不易識別,但密碼文字欄位元素很容易識別,我們可以利用它是密碼元素「上方」的「input」元素來定位文字欄位元素。

移動程式碼

By emailLocator = RelativeLocator.with(By.tagName("input")).above(By.id("password"));
email_locator = locate_with(By.TAG_NAME, "input").above({By.ID: "password"})
var emailLocator = RelativeBy.WithLocator(By.TagName("input")).Above(By.Id("password"));
      driver.find_element({relative: {tag_name: 'input', above: {id: 'password'}}})
let emailLocator = locateWith(By.tagName('input')).above(By.id('password'));
val emailLocator = RelativeLocator.with(By.tagName("input")).above(By.id("password"))

下方

如果密碼文字欄位元素由於某些原因不易識別,但電子郵件文字欄位元素很容易識別,我們可以利用它是電子郵件元素「下方」的「input」元素來定位文字欄位元素。

移動程式碼

By passwordLocator = RelativeLocator.with(By.tagName("input")).below(By.id("email"));
password_locator = locate_with(By.TAG_NAME, "input").below({By.ID: "email"})
var passwordLocator = RelativeBy.WithLocator(By.TagName("input")).Below(By.Id("email"));
      driver.find_element({relative: {tag_name: 'input', below: {id: 'email'}}})
let passwordLocator = locateWith(By.tagName('input')).below(By.id('email'));
val passwordLocator = RelativeLocator.with(By.tagName("input")).below(By.id("email"))

左方

如果取消按鈕由於某些原因不易識別,但提交按鈕元素很容易識別,我們可以利用它是提交元素「左方」的「button」元素來定位取消按鈕元素。

移動程式碼

By cancelLocator = RelativeLocator.with(By.tagName("button")).toLeftOf(By.id("submit"));
cancel_locator = locate_with(By.TAG_NAME, "button").to_left_of({By.ID: "submit"})
var cancelLocator = RelativeBy.WithLocator(By.tagName("button")).LeftOf(By.Id("submit"));
      driver.find_element({relative: {tag_name: 'button', left: {id: 'submit'}}})
let cancelLocator = locateWith(By.tagName('button')).toLeftOf(By.id('submit'));
val cancelLocator = RelativeLocator.with(By.tagName("button")).toLeftOf(By.id("submit"))

右方

如果提交按鈕由於某些原因不易識別,但取消按鈕元素很容易識別,我們可以利用它是取消元素「右方」的「button」元素來定位提交按鈕元素。

移動程式碼

By submitLocator = RelativeLocator.with(By.tagName("button")).toRightOf(By.id("cancel"));
submit_locator = locate_with(By.TAG_NAME, "button").to_right_of({By.ID: "cancel"})
var submitLocator = RelativeBy.WithLocator(By.tagName("button")).RightOf(By.Id("cancel"));
      driver.find_element({relative: {tag_name: 'button', right: {id: 'cancel'}}})
let submitLocator = locateWith(By.tagName('button')).toRightOf(By.id('cancel'));
val submitLocator = RelativeLocator.with(By.tagName("button")).toRightOf(By.id("cancel"))

附近

如果相對定位不明顯,或它根據視窗大小而變化,您可以使用 near 方法來識別最多距離提供的定位器 50px 的元素。一個很好的用例是處理一個沒有易於建構的定位器的表單元素,但其相關聯的 輸入標籤元素 卻有。

移動程式碼

By emailLocator = RelativeLocator.with(By.tagName("input")).near(By.id("lbl-email"));
email_locator = locate_with(By.TAG_NAME, "input").near({By.ID: "lbl-email"})
var emailLocator = RelativeBy.WithLocator(By.tagName("input")).Near(By.Id("lbl-email"));
      driver.find_element({relative: {tag_name: 'input', near: {id: 'lbl-email'}}})
let emailLocator = locateWith(By.tagName('input')).near(By.id('lbl-email'));
val emailLocator = RelativeLocator.with(By.tagName("input")).near(By.id("lbl-email"));

鏈結相對定位器

如果需要,您也可以鏈結定位器。有時,最容易識別元素的方法是同時位於一個元素的上方/下方和另一個元素的右方/左方。

移動程式碼

By submitLocator = RelativeLocator.with(By.tagName("button")).below(By.id("email")).toRightOf(By.id("cancel"));
submit_locator = locate_with(By.TAG_NAME, "button").below({By.ID: "email"}).to_right_of({By.ID: "cancel"})
var submitLocator = RelativeBy.WithLocator(By.tagName("button")).Below(By.Id("email")).RightOf(By.Id("cancel"));
      driver.find_element({relative: {tag_name: 'button', below: {id: 'email'}, right: {id: 'cancel'}}})
let submitLocator = locateWith(By.tagName('button')).below(By.id('email')).toRightOf(By.id('cancel'));
val submitLocator = RelativeLocator.with(By.tagName("button")).below(By.id("email")).toRightOf(By.id("cancel"))
上次修改時間 2024 年 12 月 28 日:[py]: move python code to `test_locators.py` (#2102) (79e02df42e9)