
#id, .class, tag, [attr=value], parent > child, ancestor descendant。//tag[@attr='value'], /parent/child, text(), contains(), and/or/not。//button[text()='登录']:精确文本匹配//a[contains(text(), '忘记密码')]:文本包含//input[starts-with(@id, 'email_')]:ID以指定前缀开头//div[normalize-space()='用户名']:处理空白字符干扰[attr^='prefix']:属性值以指定前缀开头 (e.g., input[id^='user-'])[attr$='suffix']:属性值以指定后缀结尾 (e.g., a[href$='.pdf'])[attr*='substr']:属性值包含指定子串 (e.g., div[class*='error-'])child:::子元素 (默认轴,可省略 child::)parent:::父元素 (e.g., //input/../label)following-sibling:::后续兄弟元素 (e.g., //tr[1]/following-sibling::tr)preceding-sibling:::前驱兄弟元素ancestor:::祖先元素 (e.g., //span/ancestor::div[@class='container'])descendant:::后代元素 (e.g., //table//descendant::input[@type='checkbox'])parent > child:直接子元素 (e.g., ul.menu > li)element + sibling:紧邻的下一个兄弟元素 (e.g., label + input)element ~ siblings:后续所有兄弟元素 (e.g., h2 ~ p)#submitBtn, .primary-button 是最快最稳定的选择。*: 尤其在路径起始位置(如 //*[...])会遍历所有元素,效率低下。应明确指定标签名或使用更具体的属性。position(), last() 等函数计算开销较大,优先考虑基于属性或关系的定位。[data-testid='login-button']//*[@data-qa='email-input']//input[@type='text' and @required and not(@disabled)]input[type='text'][required]:not([disabled])html/body/div[3]/div[2]/... 对DOM结构变化极其敏感。data-* 测试专用属性(强烈推荐): 与开发协作,为关键元素添加 data-testid, data-qa 等属性。public class LoginPage {
// 使用清晰变量名存储定位器
By usernameField = By.cssSelector("#username");
By passwordField = By.xpath("//input[@name='password' and @type='password']");
By submitButton = By.dataTestId("login-submit"); // 假设框架支持自定义定位策略
By errorMessage = By.cssSelector(".alert.alert-danger");
... // 页面操作方法loginButton, searchResultsGrid)。data-* 测试属性,并建立前端开发与测试团队的协作流程。页面结构片段:
<div class="search-container">
<input id="search-input" type="text" placeholder="搜索商品...">
<button type="submit" class="btn btn-primary search-btn" data-testid="global-search-button">
<i class="icon-search"></i> 搜索
</button>
</div>目标: 定位“搜索”提交按钮。
优选方案分析:
data-testid):button[data-testid='global-search-button']//button[@data-testid='global-search-button']#search-input + button.search-btn#search-input 之后的、类名包含 search-btn 的按钮。简洁高效。#id, .class, tag, [attr=value], parent > child, ancestor descendant。//tag[@attr='value'], /parent/child, text(), contains(), and/or/not。二、 高级定位技巧:应对复杂场景实战 场景1:定位特征模糊或动态变化的元素
//button[text()='登录']:精确文本匹配//a[contains(text(), '忘记密码')]:文本包含//input[starts-with(@id, 'email_')]:ID以指定前缀开头//div[normalize-space()='用户名']:处理空白字符干扰[attr^='prefix']:属性值以指定前缀开头 (e.g., input[id^='user-'])[attr$='suffix']:属性值以指定后缀结尾 (e.g., a[href$='.pdf'])[attr*='substr']:属性值包含指定子串 (e.g., div[class*='error-'])场景2:处理复杂层级关系与相对定位
child:::子元素 (默认轴,可省略 child::)parent:::父元素 (e.g., //input/../label)following-sibling:::后续兄弟元素 (e.g., //tr[1]/following-sibling::tr)preceding-sibling:::前驱兄弟元素ancestor:::祖先元素 (e.g., //span/ancestor::div[@class='container'])descendant:::后代元素 (e.g., //table//descendant::input[@type='checkbox'])parent > child:直接子元素 (e.g., ul.menu > li)element + sibling:紧邻的下一个兄弟元素 (e.g., label + input)element ~ siblings:后续所有兄弟元素 (e.g., h2 ~ p)场景3:构建健壮且高效的定位表达式
#submitBtn, .primary-button 是最快最稳定的选择。*: 尤其在路径起始位置(如 //*[...])会遍历所有元素,效率低下。应明确指定标签名或使用更具体的属性。position(), last() 等函数计算开销较大,优先考虑基于属性或关系的定位。[data-testid='login-button']//*[@data-qa='email-input']//input[@type='text' and @required and not(@disabled)]input[type='text'][required]:not([disabled])html/body/div[3]/div[2]/... 对DOM结构变化极其敏感。data-* 测试专用属性(强烈推荐): 与开发协作,为关键元素添加 data-testid, data-qa 等属性。三、 工程化最佳实践:构建可维护的定位体系
public class LoginPage { // 使用清晰变量名存储定位器 By usernameField = By.cssSelector("#username"); By passwordField = By.xpath("//input[@name='password' and @type='password']"); By submitButton = By.dataTestId("login-submit"); // 假设框架支持自定义定位策略 By errorMessage = By.cssSelector(".alert.alert-danger"); ... // 页面操作方法
loginButton, searchResultsGrid)。data-* 测试属性,并建立前端开发与测试团队的协作流程。四、 实战案例解析:电商网站搜索按钮定位 页面结构片段: <div class="search-container"> <input id="search-input" type="text" placeholder="搜索商品..."> <button type="submit" class="btn btn-primary search-btn" data-testid="global-search-button"> <i class="icon-search"></i> 搜索 </button> </div> 目标: 定位“搜索”提交按钮。 优选方案分析:
data-testid):button[data-testid='global-search-button']//button[@data-testid='global-search-button']#search-input + button.search-btn#search-input 之后的、类名包含 search-btn 的按钮。简洁高效。//button[contains(@class, 'search-btn') and contains(., '搜索')]search-btn 且内部文本包含“搜索”的按钮。适应性强,但效率略低于CSS。五、 总结与关键行动点 核心结论:
data-* 测试属性是定位稳定性的黄金标准,应积极推动落地。行动建议:
data-testid 等测试属性的添加规范与流程。$x()/$$())验证定位器有效性。掌握精确定位的艺术,是构建高可靠性自动化测试的起点。 通过科学选择定位技术、应用高级技巧并践行工程化最佳实践,可显著提升测试脚本的健壮性与执行效率,为软件质量保驾护航。
//button[contains(@class, 'search-btn') and contains(., '搜索')]search-btn 且内部文本包含“搜索”的按钮。适应性强,但效率略低于CSS。核心结论:
data-* 测试属性是定位稳定性的黄金标准,应积极推动落地。行动建议:
data-testid 等测试属性的添加规范与流程。$x()/$$())验证定位器有效性。掌握精确定位的艺术,是构建高可靠性自动化测试的起点。 通过科学选择定位技术、应用高级技巧并践行工程化最佳实践,可显著提升测试脚本的健壮性与执行效率,为软件质量保驾护航。
本文原创于【程序员二黑】公众号,转载请注明出处!
欢迎大家关注笔者的公众号:程序员二黑,专注于软件测试干货分享
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。