116.md 13.7 KB
Newer Older
W
wizardforcel 已提交
1
# 9o。 WebDriver – 定位元素:第 4b 部分(由 XPath 续)
W
init  
wizardforcel 已提交
2 3 4 5 6

> 原文: [https://javabeginnerstutorial.com/selenium/9o-webdriver-locating-elements-4b/](https://javabeginnerstutorial.com/selenium/9o-webdriver-locating-elements-4b/)

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

W
wizardforcel 已提交
7
这是我们上一篇文章“ [9n。 WebDriver – 定位元素:第 4a 部分(由 XPath 提供)](https://javabeginnerstutorial.com/selenium/9n-webdriver-locating-elements-4a/)”。 您以前曾经听过我说过这个,然后您会再次听我说过……在继续使用 XPath 策略之前,请先阅读第 4a 部分。
W
init  
wizardforcel 已提交
8 9 10

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

W
wizardforcel 已提交
11 12 13
1.  使用 Text()
2.  使用 starts-with()
3.  使用 XPath 轴
W
init  
wizardforcel 已提交
14

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

W
wizardforcel 已提交
17
## 1.使用 text()
W
init  
wizardforcel 已提交
18 19 20

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

W
wizardforcel 已提交
21
***即时贴:***
W
init  
wizardforcel 已提交
22 23 24

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

W
wizardforcel 已提交
25
***示例*** **让我们找到“ Facebook 注册”页面上的“忘记帐户?”链接。
W
init  
wizardforcel 已提交
26

W
wizardforcel 已提交
27
右键点击“忘记帐户?”链接,然后选择检查元素以获取相应的 HTML 代码,如下所示,
W
init  
wizardforcel 已提交
28 29 30 31 32 33

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

W
wizardforcel 已提交
34
让我们通过提供出现在 Facebook 页面上的文本来找到此链接。
W
init  
wizardforcel 已提交
35 36 37 38 39 40 41

*代码:*

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

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

W
wizardforcel 已提交
44
让我们尝试在同一示例中同时实现 contains()和 text()。 由于我们只有一个链接与该文本,因此将使用 findElement 方法。
W
init  
wizardforcel 已提交
45 46 47 48 49

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

W
wizardforcel 已提交
50
## 2.使用 starts-with()
W
init  
wizardforcel 已提交
51

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

W
wizardforcel 已提交
54
***示例*** **让我们在“ Facebook 注册”页面上找到“新密码”文本框。
W
init  
wizardforcel 已提交
55

W
wizardforcel 已提交
56
右键点击“新密码”文本框,然后选择检查元素以获取相应的 HTML 代码,
W
init  
wizardforcel 已提交
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77

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

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

```java
<input class="inputtext" name="pass" id="pass" tabindex="2" type="password">
```

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

*Code:*

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

W
wizardforcel 已提交
78
## 3.使用 XPath 轴
W
init  
wizardforcel 已提交
79

W
wizardforcel 已提交
80
XPath 轴定义在当前节点浏览 DOM 的树形结构时要考虑的相对于当前节点的节点集或方向。
W
init  
wizardforcel 已提交
81

W
wizardforcel 已提交
82
下表(礼貌性表示: [w3schools](https://www.w3schools.com/xml/xpath_axes.asp) )显示了所有 13 个可用的 XPath 轴及其结果。
W
init  
wizardforcel 已提交
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100

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

让我们来看一些重要的

W
wizardforcel 已提交
101
### 3a。 父轴
W
init  
wizardforcel 已提交
102 103 104

选择当前节点的父级。

W
wizardforcel 已提交
105
***示例*** *:*让我们找到位于 Facebook Sign Up 页面左上方的 Facebook 徽标的锚标记。
W
init  
wizardforcel 已提交
106 107 108 109 110 111

在检查元素后,

```java
<a href="https://www.facebook.com/" title="Go to Facebook Home">
   <i class="fb_logo img sp_euCDsy2vhU4 sx_af4dba">
W
wizardforcel 已提交
112
       Facebook
W
init  
wizardforcel 已提交
113 114 115 116 117 118 119 120 121 122
   </i>
</a> 
```

*Code:*

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

W
wizardforcel 已提交
123
将找到具有 href 和 title 属性的父节点“ a”。
W
init  
wizardforcel 已提交
124

W
wizardforcel 已提交
125
### 3b。 祖先轴
W
init  
wizardforcel 已提交
126 127 128

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

W
wizardforcel 已提交
129
***示例*** *:*让我们在“ Facebook 注册”页面上找到文字“生日”。
W
init  
wizardforcel 已提交
130 131 132 133 134 135 136 137 138 139 140

Upon inspecting the element,

Birthday

*Code:*

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

W
wizardforcel 已提交
141
带有 ID 的“选择”标签,选择了“月”。 转到类“ _5k_5”的祖先 div 标签。 然后到其前一个带有“ div”标签的同级节点,其文本为“ Birthday”。
W
init  
wizardforcel 已提交
142 143 144

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

W
wizardforcel 已提交
145
### 3c。 子轴
W
init  
wizardforcel 已提交
146 147 148

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

W
wizardforcel 已提交
149
***示例*** *:*让我们找到“ Facebook 注册”页面上的“登录”按钮。
W
init  
wizardforcel 已提交
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164

Upon inspecting the element,

```java
 <label class="uiButton uiButtonConfirm" for="u_0_q" id="loginbutton"></label> 
```

*Code:*

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

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

W
wizardforcel 已提交
165
### 3d。 后裔轴
W
init  
wizardforcel 已提交
166 167 168

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

W
wizardforcel 已提交
169
***示例*** *:*让我们在“ Facebook 注册”页面上找到“名字”文本框。
W
init  
wizardforcel 已提交
170 171 172 173 174

Upon inspecting the element,

First name

W
wizardforcel 已提交
175
<输入 id =“ u_0_1”类=“ inputtext _58mg _5dba _2ph-” data-type =“ text” name =“ firstname” aria-required =“ 1” placeholder =“”“ aria-label =” First name“类型 =“文字” > < / div >
W
init  
wizardforcel 已提交
176 177 178 179 180 181 182

*Code:*

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

W
wizardforcel 已提交
183
类别为'uiStickyPlaceholderInput'的'div'标签的后代节点-ID 为'u_o_1'的输入标签已找到。
W
init  
wizardforcel 已提交
184

W
wizardforcel 已提交
185
### 3e。 从动轴
W
init  
wizardforcel 已提交
186 187 188

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

W
wizardforcel 已提交
189
***示例*** *:*让我们在“ Facebook 注册”页面页脚部分中找到“登录”链接。
W
init  
wizardforcel 已提交
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207

Upon inspecting the element,

```java
<td class="_51m- hLeft plm">
   <a href="/r.php" title="Sign Up for Facebook">Sign Up</a>
</td>
<td class="_51m- hLeft plm">
   <a href="/login/" title="Log into Facebook">Log In</a>
</td> 
```

*Code:*

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

W
wizardforcel 已提交
208
以下 td 标签的同级类 _51m-hLeft plm 是另一个 td 标签,其子对象是带有标题“登录 Facebook”的锚标签。
W
init  
wizardforcel 已提交
209 210 211

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

W
wizardforcel 已提交
212
### 3f。 上一个同级轴
W
init  
wizardforcel 已提交
213 214 215

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

W
wizardforcel 已提交
216
***示例*** *:*让我们找到“ Facebook 注册”页面上的“女性”单选按钮。
W
init  
wizardforcel 已提交
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234

Upon inspecting the element,

```java
<span class="_5k_2 _5dba">
   <input id="u_0_g" name="sex" value="1" type="radio">
   <label class="_58mt" for="u_0_g">Female</label>
</span> 
```

*Code:*

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

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

W
wizardforcel 已提交
235
这样,就涵盖了一些常用的 XPath 轴类型。
W
init  
wizardforcel 已提交
236

W
wizardforcel 已提交
237
我们在 BrainBell 方面一直处于停滞状态。 那为什么要延迟呢? 开始了,
W
init  
wizardforcel 已提交
238 239 240

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

W
wizardforcel 已提交
241 242 243
*   *症状:* *没有任何东西被注册,开始浏览文章或忘记您刚刚阅读的内容。*
*   *诊断:* *您的大脑超负荷。*
*   *Remedy:* *Take a break! But remember to be back soon 😉*
W
init  
wizardforcel 已提交
244

W
wizardforcel 已提交
245
*我将根据我的经验个人建议 **Pomodoro 技术**。 它非常有效。 试一试!*
W
init  
wizardforcel 已提交
246 247 248 249 250 251 252

## 总体图片

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

*场景*

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

W
wizardforcel 已提交
273
此方案的 JUnit 代码是,
W
init  
wizardforcel 已提交
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359

```java
package com.blog.junitTests;

import java.util.concurrent.TimeUnit;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;

public class ElementLocatorTest4b {
    // Declaring variables
    private WebDriver driver;
    private String baseUrl;

    @Before
    public void setUp() throws Exception {
        // Selenium version 3 beta releases require system property set up
        System.setProperty("webdriver.gecko.driver", "E:\\Softwares\\Selenium\\geckodriver-v0.10.0-win64\\geckodriver.exe");
        // Create a new instance for the class FirefoxDriver
        // that implements WebDriver interface
        driver = new FirefoxDriver();
        // Implicit wait for 5 seconds
        driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
        // Assign the URL to be invoked to a String variable
        baseUrl = "https://www.facebook.com/";
    }

    @Test
    public void testPageTitle() throws Exception {
        // Open baseUrl in Firefox browser window
        driver.get(baseUrl);

        // Locate 'Forgot Account' link using XPath: text()
        WebElement forgotAccLink = driver.findElement(By.xpath("//*[contains(text(),'Forgot')]"));
        // Prints the link text to the console
        System.out.println("Link text: " + forgotAccLink.getText());
        // Locate 'New password' text box by XPath: using starts-with()
        WebElement passwordNew = driver.findElement(By.xpath("(//input[starts-with(@type,'pass')])[2]"));
        // Clear the default placeholder or any value present
        passwordNew.clear();
        // Enter/type the value to the text box
        passwordNew.sendKeys("test1234!");

        // Locate 'Log In' button using XPath: child axis
        WebElement logIn = driver.findElement(By.xpath("//label[@id='loginbutton']/child::input"));
        // Prints 'value' attribute to console
        System.out.println("Child axis: " + logIn.getAttribute("value"));
        // Locate 'Facebook' logo using XPath: parent axis
        WebElement fbLogo = driver.findElement(By.xpath("//i[contains(@class,'fb_logo')]/parent::a"));
        // Prints 'title' attribute's value to console
        System.out.println("Parent axis: " + fbLogo.getAttribute("title"));
        // Locate 'Log In' link in footer section using XPath: following-sibling axis
        WebElement loginFooter = driver.findElement(By.xpath("//td[@class='_51m- hLeft plm']/following-sibling::td/child::a"));
        //Prints 'title' attribute's value to console
        System.out.println("Following-sibling: " + loginFooter.getAttribute("title"));
        // Locate 'female' radio button using XPath: preceding-sibling axis
        WebElement femaleRadioBtn = driver.findElement(By.xpath("//label[@class='_58mt']/preceding-sibling::input"));
        // Click the radio button
        femaleRadioBtn.click();
        // Locate 'Birthday' text using XPath: ancestor axis
        WebElement birthday = driver.findElement(By.xpath("//select[@id='month']/ancestor::div[@class='_5k_5']/preceding-sibling::div"));
        //Prints text to console
        System.out.println("Ancestor axis: " + birthday.getText());
        // Locate 'first name' test box using XPath: descendant axis
        WebElement firstName = driver.findElement(By.xpath("//div[contains(@class,'uiStickyPlaceholderInput')]/descendant::input"));
        firstName.clear();
        firstName.sendKeys("test first");
    }

    @After
    public void tearDown() throws Exception {
        // Close the Firefox browser
        driver.close();
    }
}
```

*执行结果:*

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

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

![XPath JUnit Console](img/044fb8d15c96e0bbc42010e4396dd739.png)

W
wizardforcel 已提交
364
下图显示了成功执行测试脚本后获得的 Firefox 输出。
W
init  
wizardforcel 已提交
365 366 367 368 369 370 371

![XPath Firefox output](img/c696b7d190e210595629764b59692033.png)

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

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