Skip to content

Selenium - 定位器

定位器(Locators)是 Selenium 用来查找网页上元素的核心机制。选择正确的定位器策略对于创建稳定且易于维护的自动化测试至关重要。Selenium WebDriver 通过 By 类提供了几种定位器策略。

查找元素的主要方法有:

  • driver.findElement(By locator): 返回匹配指定定位器策略的第一个 WebElement 对象。如果没有找到元素,则抛出 NoSuchElementException。
  • driver.findElements(By locator): 返回包含所有匹配定位器策略的元素的 List<WebElement> 列表。如果没有找到元素,则返回一个空列表。

以下是 WebDriver 中常用的定位器策略及其使用技巧:

策略Java 语法示例描述与最佳实践
By IDdriver.findElement(By.id("userId"))使用元素的唯一 id 属性来定位。**推荐:**ID 通常是唯一的且不太可能改变,这使得测试更加健壮。
By Namedriver.findElement(By.name("username"))使用 name 属性来定位元素。适用于表单元素,但需确保 name 值稳定。
By CSS Selectordriver.findElement(By.cssSelector("input[type='submit']"))使用 CSS 选择器语法来定位元素。**强烈推荐:**功能强大、简洁,通常比 XPath 更快。适用于复杂选择以及根据属性或关系定位元素。
By XPathdriver.findElement(By.xpath("//button[contains(text(),'Login')]"))使用 XPath (XML Path Language) 来定位元素。**强大但慎用:**非常灵活,可以通过复杂方式遍历 DOM (例如,查找父/兄弟元素)。可能比 CSS 慢,并且如果基于绝对路径或索引则很脆弱。优先使用相对 XPath 表达式。
By Link Textdriver.findElement(By.linkText("Forgot Password"))通过锚点元素(<a>)的精确可见文本来定位。仅在链接文本唯一且静态时使用。
By Partial Link Textdriver.findElement(By.partialLinkText("Forgot"))通过锚点元素(<a>)可见文本的部分匹配来定位。如果部分链接文本是动态的,这很有用,但如果多个链接共享部分文本,可能导致不正确的匹配。
By Class Namedriver.findElement(By.className("btn-primary"))使用 class 属性来定位元素。通常返回多个元素(使用 findElements)。谨慎使用,因为类名可能非唯一或经常因样式目的而改变。
By Tag Namedriver.findElements(By.tagName("img"))按 HTML 标签名(例如,div、a、input)来定位元素。通常与 findElements 一起使用以获取元素集合。

选择定位器时,应追求以下特性:

  • **唯一:**仅标识预期的元素。
  • **稳定:**不易因 UI 重新设计或动态内容而改变。
  • **描述性:**易于理解定位器指向的是哪个元素。
  • **简洁:**通常优先选择较短的定位器(如 ID 或优秀的 CSS 选择器)。

通常的优先顺序是:ID > Name > CSS Selector > XPath > Link Text > Partial Link Text > Class Name > Tag Name。然而,最佳选择取决于具体的 HTML 结构。

忘记过时的插件,如 Firebug/FirePath。现代浏览器(Chrome、Firefox、Edge)内置了出色的开发者工具(通常按 F12 访问)。使用“检查元素”功能(通常是箭头图标)在页面上选择一个元素。工具会显示 HTML 结构、属性(如 ID、name、class),并通常会建议 CSS Selectors 或 XPath。

假设您想查找一个 HTML 代码为 <button id="loginBtn" class="submit primary" type="submit">Log In</button> 的登录按钮。

可能的定位器:

// 推荐:
WebElement loginButtonById = driver.findElement(By.id("loginBtn"));
// 同样不错:
WebElement loginButtonByCss = driver.findElement(By.cssSelector("button#loginBtn")); // 使用 ID
WebElement loginButtonByCssType = driver.findElement(By.cssSelector("button[type='submit']")); // 使用属性
// 尚可,但如果文本改变,健壮性可能较差:
WebElement loginButtonByXpath = driver.findElement(By.xpath("//button[text()='Log In']"));
// 不太理想,如果类名改变或非唯一:
WebElement loginButtonByClass = driver.findElement(By.className("submit")); // 可能找到其他元素

在浏览器的开发者控制台中尝试不同的策略,为您的具体应用找到最可靠的选项。