9O WebDriver – 定位元素:第 4b 部分(XPath 续)

原文: https://javabeginnerstutorial.com/selenium/9o-webdriver-locating-elements-4b/

嗨冠军! 欢迎来到我们关于定位元素的最后一篇文章。 好极了!!!

这是我们上一篇文章“9n。 WebDriver – 定位元素:第 4a 部分(由 XPath 提供)”。 您以前曾经听过我说过这个,然后您会再次听我说过……在继续使用 XPath 策略之前,请先阅读第 4a 部分。

在这篇文章中,我们将研究以下技术,

  1. 使用Text()
  2. 使用starts-with()
  3. 使用 XPath 轴

这些技术以及我们在第 4a 部分中看到的技术可以结合起来,并用于形成有效的 XPath,该 XPath 可以定位网页上的任何元素。 现在通过示例来介绍当今的技术。

1.使用text()

通过提供与网页上显示的文本完全相同的文本,这是一种轻松定位元素的方法。

注意:

当心! 即使错误地包含空格,您也可能遇到“ElementNotFound”异常。 在代码中提供的文本必须与可见文本完全匹配,这一点非常重要,我的意思是从字面上看!

示例:让我们找到“Facebook 注册”页面上的“忘记帐户?”链接。

右键点击“忘记帐户?”链接,然后选择检查元素以获取相应的 HTML 代码,如下所示,

  1. <a href="https://www.facebook.com/recover/initiate?lwv=111"
  2. data-testid="forgot_account_link">Forgot account?</a>

让我们通过提供出现在 Facebook 页面上的文本来找到此链接。

代码:

  1. driver.findElement(By.xpath("//a[text()='Forgot account?']"));

如果要查找包含部分文本的所有元素,可以将contains()text()技术结合使用。 可以使用findElements方法在列表中获取所有元素。

让我们尝试在同一示例中同时实现contains()text()。 由于我们只有一个链接与该文本,因此将使用findElement方法。

  1. driver.findElement(By.xpath("//*[contains(text(),'Forgot')]"));

2.使用starts-with()

通过指定属性的部分值(前缀),可以使用starts-with()查找元素。 当页面重新加载时属性值动态更改时,此功能非常有用。

示例:让我们在“Facebook 注册”页面上找到“新密码”文本框。

右键点击“新密码”文本框,然后选择检查元素以获取相应的 HTML 代码,

  1. <input class="inputtext _58mg _5dba _2ph-" data-type="text"
  2. name="reg_passwd__" aria-required="1" placeholder="" id="u_0_d"
  3. aria-label="New password" type="password">

让我们通过提供type属性的部分前缀值“通过”来找到此文本框。 请注意,“登录”部分中的密码字段还具有type作为password

  1. <input class="inputtext" name="pass" id="pass" tabindex="2" type="password">

因此,第二个元素必须位于我们的案例中。

代码:

  1. driver.findElement(By.xpath("(//input[starts-with(@type,'pass')])[2]"));

3.使用 XPath 轴

XPath 轴定义在当前节点浏览 DOM 的树形结构时要考虑的相对于当前节点的节点集或方向。

下表(礼貌性表示: w3schools )显示了所有 13 个可用的 XPath 轴及其结果。

轴名称结果
祖先选择当前节点的所有祖先(父,祖父级等)
祖先或自己选择当前节点的所有祖先(父,祖父级等)和当前节点本身
属性选择当前节点的所有属性
子项选择当前节点的所有子节点
后代选择当前节点的所有后代(子代,孙代等)
后代或自己选择当前节点的所有后代(子代,孙代等)和当前节点本身
之后选择当前节点的结束标记之后的文档中的所有内容
之后的同级选择当前节点之后的所有同级
命名空间选择当前节点的所有名称空间节点
父项选择当前节点的父节点
之前选择出现在文档中当前节点之前的所有节点,但祖先,属性节点和名称空间节点除外
之前的同级选择当前节点之前的所有同级
自己选择当前节点

让我们来看一些重要的

3a. 父轴

选择当前节点的父级。

示例:让我们找到位于 Facebook Sign Up 页面左上方的 Facebook 徽标的锚标记。

在检查元素后,

  1. <a href="https://www.facebook.com/" title="Go to Facebook Home">
  2. <i class="fb_logo img sp_euCDsy2vhU4 sx_af4dba">
  3. Facebook
  4. </i>
  5. </a>

代码:

  1. driver.findElement(By.xpath("//i[@class='fb_logo']/parent::a"));

将找到具有hreftitle属性的父节点“a”。

3b. 祖先轴

选择当前节点的所有祖先(父代,祖父级等)。

示例:让我们在“Facebook 注册”页面上找到文字“生日”。

Upon inspecting the element,

Birthday

代码:

  1. driver.findElement(By.xpath("//select[@id='month']/ancestor::div[@class='_5k_5']/preceding-sibling::div"));

带有 ID 的“select”标签,选择了“month”。 转到类“_5k_5”的祖先div标签。 然后到其前一个带有“div”标签的同级节点,其文本为“Birthday”。

选择该特定示例以显示可以组合多个轴以获得所需的结果。

3c. 子轴

选择当前节点的所有子节点

示例:让我们找到“Facebook 注册”页面上的“登录”按钮。

Upon inspecting the element,

  1. <label class="uiButton uiButtonConfirm" for="u_0_q" id="loginbutton"></label>

代码:

  1. driver.findElement(By.xpath("//label[@id='loginbutton']/child::input"));

标识为“loginbutton”的标签的子节点-标识为“u_0_q”的输入标签。

3d. 后代轴

选择当前节点的所有后代(子代,孙代等)。

示例:让我们在“Facebook 注册”页面上找到“名字”文本框。

Upon inspecting the element,

First name

  1. <input id=”u_0_1″ class=”inputtext _58mg _5dba _2ph-” data-type=”text” name=”firstname” aria-required=”1″ placeholder=”” aria-label=”First nametype=”text”> </div>

代码:

  1. driver.findElement(By.xpath("//div[contains(@class,'uiStickyPlaceholderInput')]/descendant::input"));

类别为uiStickyPlaceholderInputdiv标签的后代节点-ID 为u_o_1的输入标签已找到。

3e. 同级轴

选择当前节点之后的所有同级

示例:让我们在“Facebook 注册”页面页脚部分中找到“登录”链接。

Upon inspecting the element,

  1. <td class="_51m- hLeft plm">
  2. <a href="/r.php" title="Sign Up for Facebook">Sign Up</a>
  3. </td>
  4. <td class="_51m- hLeft plm">
  5. <a href="/login/" title="Log into Facebook">Log In</a>
  6. </td>

代码:

  1. driver.findElement(By.xpath("//td[@class='_51m- hLeft plm']/following-sibling::td/child::a"));

以下td标签的同级类_51m-hLeft plm是另一个td标签,其子对象是带有标题“登录 Facebook”的锚标签。

将后继同级和子级轴组合在一起,以在页脚部分中找到“登录”超链接。

3f. 上一个同级轴

选择当前节点之前的所有同级

示例:让我们找到“Facebook 注册”页面上的“女性”单选按钮。

Upon inspecting the element,

  1. <span class="_5k_2 _5dba">
  2. <input id="u_0_g" name="sex" value="1" type="radio">
  3. <label class="_58mt" for="u_0_g">Female</label>
  4. </span>

代码:

  1. driver.findElement(By.xpath("//label[@class='_58mt']/preceding-sibling::input"));

“标签”标签的前面同级是“无线电”类型的input标签。 这样就找到了所需的单选按钮。

这样,就涵盖了一些常用的 XPath 轴类型。

我们在 BrainBell 方面一直处于停滞状态。 那为什么要延迟呢? 开始了,

BrainBell注意! 注意您的大脑状态。

  • 症状:没有任何东西被注册,开始浏览文章或忘记您刚刚阅读的内容。
  • 诊断:您的大脑超负荷。
  • 补救:休息一下! 但是记得很快回来😉

我将根据我的经验个人建议 Pomodoro 技术。 它非常有效。 试一试!

概览

让我们来看一个测试案例,该案例实现了迄今为止本文中涵盖的所有技术,

场景

  1. 打开 Firefox 浏览器。
  2. 导航到 www.facebook.com
  3. 使用text()找到“忘记帐户?”链接
  4. 将链接文本打印到控制台
  5. 使用starts-with()找到“新密码”文本框
  6. 输入值“test1234!
  7. 使用子轴找到“登录”按钮
  8. 将值属性打印到控制台
  9. 使用父轴找到 Facebook 徽标
  10. 将其title属性的值打印到控制台
  11. 在页脚部分的“兄弟姐妹”轴中找到“登录”链接
  12. 将其title属性的值打印到控制台
  13. 使用上一个同级轴找到“女性”单选按钮
  14. 点击单选按钮
  15. 使用祖先轴找到文本“生日”
  16. 将其文本打印到控制台
  17. 使用后代轴找到“名字”文本框
  18. 输入值“首先测试”
  19. 验证 Eclipse IDE 控制台的输出屏幕和 JUnit 窗格是否成功

此方案的 JUnit 代码是,

  1. package com.blog.junitTests;
  2. import java.util.concurrent.TimeUnit;
  3. import org.junit.After;
  4. import org.junit.Before;
  5. import org.junit.Test;
  6. import org.openqa.selenium.By;
  7. import org.openqa.selenium.WebDriver;
  8. import org.openqa.selenium.WebElement;
  9. import org.openqa.selenium.firefox.FirefoxDriver;
  10. public class ElementLocatorTest4b {
  11. // Declaring variables
  12. private WebDriver driver;
  13. private String baseUrl;
  14. @Before
  15. public void setUp() throws Exception {
  16. // Selenium version 3 beta releases require system property set up
  17. System.setProperty("webdriver.gecko.driver", "E:\\Softwares\\Selenium\\geckodriver-v0.10.0-win64\\geckodriver.exe");
  18. // Create a new instance for the class FirefoxDriver
  19. // that implements WebDriver interface
  20. driver = new FirefoxDriver();
  21. // Implicit wait for 5 seconds
  22. driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
  23. // Assign the URL to be invoked to a String variable
  24. baseUrl = "https://www.facebook.com/";
  25. }
  26. @Test
  27. public void testPageTitle() throws Exception {
  28. // Open baseUrl in Firefox browser window
  29. driver.get(baseUrl);
  30. // Locate 'Forgot Account' link using XPath: text()
  31. WebElement forgotAccLink = driver.findElement(By.xpath("//*[contains(text(),'Forgot')]"));
  32. // Prints the link text to the console
  33. System.out.println("Link text: " + forgotAccLink.getText());
  34. // Locate 'New password' text box by XPath: using starts-with()
  35. WebElement passwordNew = driver.findElement(By.xpath("(//input[starts-with(@type,'pass')])[2]"));
  36. // Clear the default placeholder or any value present
  37. passwordNew.clear();
  38. // Enter/type the value to the text box
  39. passwordNew.sendKeys("test1234!");
  40. // Locate 'Log In' button using XPath: child axis
  41. WebElement logIn = driver.findElement(By.xpath("//label[@id='loginbutton']/child::input"));
  42. // Prints 'value' attribute to console
  43. System.out.println("Child axis: " + logIn.getAttribute("value"));
  44. // Locate 'Facebook' logo using XPath: parent axis
  45. WebElement fbLogo = driver.findElement(By.xpath("//i[contains(@class,'fb_logo')]/parent::a"));
  46. // Prints 'title' attribute's value to console
  47. System.out.println("Parent axis: " + fbLogo.getAttribute("title"));
  48. // Locate 'Log In' link in footer section using XPath: following-sibling axis
  49. WebElement loginFooter = driver.findElement(By.xpath("//td[@class='_51m- hLeft plm']/following-sibling::td/child::a"));
  50. //Prints 'title' attribute's value to console
  51. System.out.println("Following-sibling: " + loginFooter.getAttribute("title"));
  52. // Locate 'female' radio button using XPath: preceding-sibling axis
  53. WebElement femaleRadioBtn = driver.findElement(By.xpath("//label[@class='_58mt']/preceding-sibling::input"));
  54. // Click the radio button
  55. femaleRadioBtn.click();
  56. // Locate 'Birthday' text using XPath: ancestor axis
  57. WebElement birthday = driver.findElement(By.xpath("//select[@id='month']/ancestor::div[@class='_5k_5']/preceding-sibling::div"));
  58. //Prints text to console
  59. System.out.println("Ancestor axis: " + birthday.getText());
  60. // Locate 'first name' test box using XPath: descendant axis
  61. WebElement firstName = driver.findElement(By.xpath("//div[contains(@class,'uiStickyPlaceholderInput')]/descendant::input"));
  62. firstName.clear();
  63. firstName.sendKeys("test first");
  64. }
  65. @After
  66. public void tearDown() throws Exception {
  67. // Close the Firefox browser
  68. driver.close();
  69. }
  70. }

执行结果:

这段代码将作为本文讨论的每种技术的一部分进行解释。

在 JUnit 窗口中,绿色条显示测试用例已成功执行。 控制台窗口显示没有任何错误。 它还可以按预期显示所有打印结果。

XPath JUnit Console

下图显示了成功执行测试脚本后获得的 Firefox 输出。

XPath Firefox output

好吧! 现在,您应该全都适应定位策略。 我们将在所有即将到来的示例中看到这些策略的应用。 因此,请继续关注此空间。

在另一个帖子中再见! 祝你有美好的一天!