Seleniumで要素を選択する方法まとめ

Seleniumの findElement, findElementsメソッドでHTML要素を選択する方法のまとめです。

個人的に(自動生成された等の理由により)カスタマイズ不可なサイトをテストすることが多く、主に次の画面に遷移する際の要素選択について、使ったことのあるパターンをまとめてみました。

各項のスクリーンショットは、上がサイトの例、下がChromeの検証機能(デベロッパーツール)で要素を表示したものです。なるべくそのまま載せるようにしましたが、Qiita用に横幅を短くしたり、実データは削除したりと、多少修正しているものもあります。

# 1) id属性 で検索

id属性 で検索できる例：

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/172826/31649503-1e07-0583-7d41-587fc9ca4edd.png)|
|:-:|

目的のHTML要素にid属性 が設定してある場合、それを指定して検索するだけです。

```java
driver.findElement(By.id("service_category_cloud_Expert")).click();
```

全部こんなサイトならテストも簡単です（というよりこの記事がいらないです）。

# 2) name属性 で検索

name属性 で検索できる例：

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/172826/8667b3cf-f6b1-100b-6c05-cf51024406d8.png)|
|:-:|

name属性 も基本的には一意なので、指定するだけです。

```java
driver.findElement(By.name("Submit")).click();
```

# 3) class属性 で検索

一意のclass属性 で検索できる例：

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/172826/6e4fafa9-101a-d77d-c5cd-61458bf4081a.png)|
|:-:|

目的のclass属性 が1つしか無いことが期待されている場合は、id, name属性 と同様にfindElement()で取得可能です。この例であれば、「次へ進む」ボタン(btn_nextクラス)はサイトに1つだけであることが期待されているので、クラス指定でそのまま取得しています。もし同一classを持つ要素が複数あった場合は、最初のものが返されます。

```java
driver.findElement(By.className("btn_next")).click();
// driver.findElements(By.className("btn_next")).get(0).click(); と同じ
```

同じclass属性 が複数ある例：

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/172826/1003d574-6968-b839-a477-425c5466e027.png)|
|:-:|

複数ある場合はリストで取得し、その中から目的のリンクを見つけるために、追加の処理が必要となります。この例では"aria-label"という属性を使って、クリックする要素を特定しています。

```java
List<WebElement> elements = driver.findElements(By.className("mv-tile"));
WebElement targetElement = null;
for (WebElement element: elements ) {
    if (element.getAttribute("aria-label").contains("Publickey")) {
        targetElement = element;
    }
}
targetElement.click(); // if文の中でクリックすると、後ろに該当しない要素がある場合にExceptionが発生します
```

# 4) title属性 で検索

ここからはxpathにより特定するパターンとなります。

title属性 で検索できる例：

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/172826/11fc111f-7c19-08b4-f6b8-aabfa839ab3a.png)|
|:-:|

特定のタイトルを持つタグは以下のように検索します。この例では、'公開レポート'というタイトルを持つ aタグを検索しています。

```java
driver.findElement(By.xpath("//a[@title='公開レポート']")).click();
```

タイトルが長い場合はcontainsで部分検索も可能です。

```java
driver.findElement(By.xpath("//a[contains(@title,'長いタイトルの一部')]")).click();
```

title属性 が設定されているものは他のタグも同様に検索できます。
特定のタイトルを持つ inputタグの場合は以下のようになります。

```java
driver.findElement(By.xpath("//input[@title='お名前']")).sendKeys("てすと　一郎");
driver.findElement(By.xpath("//input[contains(@title,'タイトルの一部')]")).sendKeys("本文入力");
```

# 5) value属性 で検索

value属性 で検索できる例：

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/172826/1b98992e-8b1c-3020-4a42-2c7c079ce931.png)|
|:-:|

value属性も、タイトル同様にタグとの組み合わせで検索します。

```java
driver.findElement(By.xpath("//input[@value='000200']")).click();
```

# 6) alt属性 で検索

alt属性 で検索できる例：

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/172826/d06a9481-0120-df99-034e-bbf9fd955607.png)|
|:-:|

alt属性もタグとの組み合わせで検索します。altは長いことが多いので、部分一致の方を使う場合が多いと思います。

```java
driver.findElement(By.xpath("//a[contains(@alt,'お問い合わせ')]")).click();
```

あまりありませんが完全一致も可能です。

```java
driver.findElement(By.xpath("//input[@alt=\"登録\"]")).click();
```

# 7) タグで検索

ここからはタグなど、htmlの構造で検索するパターンです。

タグで検索できる例：

|![68747470733a2f2f71696974612d696d616782e706e67.png](https://qiita-image-store.s3.amazonaws.com/0/172826/b2f8ba10-edcb-5c30-8ee7-3312abc3c0fe.png)|
|:-:|

同じタグを持つ要素をリストで取得し、その中から目的のリンクを見つける処理は 3) 複数classと同様の処理になります。この例では"alt"属性を使って特定しています。

```java
List<WebElement> elements = driver.findElements(By.tagName("img"));
WebElement targetElement = null;
for (WebElement element : elements) {
    if (element.getAttribute("alt").equals("社内業務")) {
        targetElement = element;
    }
}
targetElement.click();
```

なお、この例では絞り込み条件がaltなので、6) alt属性の記法でも取得できます。(タグと属性の組み合わせによって、どちらを使うか悩ましいところです。)

```java
driver.findElement(By.xpath("//img[@alt=\"社内業務\"]")).click();
```

また、タグも1つだけの場合はfindElementで検索できますが、これは滅多に無いと思います。

```java
driver.findElement(By.tagName("img")).click();
// driver.findElements(By.tagName("img")).get(0).click(); と同じ
```

# 8) パス指定(テーブル検索)

テーブル検索の例：

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/172826/4e118a9f-bce0-748e-bb26-9bc8b1f31945.png)|
|:-:|

テーブルに汎用的なclassしか付いていないような場合は、テーブルのパスで取得します。この例では、表示内容に改行やコメントが入っているため、indexOf メソッドで目的の文字列を検索しています。

```java
List<WebElement> tableElements = driver.findElements(By.xpath("//table[@class='table1']/tbody/tr/td/a"));
WebElement targetElement = null;
for(WebElement element : tableElements) {
    if (element.getText().indexOf("PRODUCT002") != -1) {
        targetElement = element;
    }
}
targetElement.click();
```

# 9) パス指定(リスト検索)

リスト検索の例：

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/172826/9b17e394-cf8d-cd73-380d-ed5d93a5f41c.png)|
|:-:|

テーブルと同様に、パス検索 → 各要素内のテキスト検索の流れになります。

```java
List<WebElement> listElements = driver.findElements(By.xpath("//ul[@class='nav navbar-nav navbar-right']/li/a"));
WebElement targetElement = null;
for(WebElement element : listElements ) {
    if (element.getText().indexof("PRODUCT002") > 1) {
        targetElement = element;
    }
}
targetElement.click();
```

# 10) label で検索

label で検索できる例：

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/172826/3e65c753-e83a-3414-f3a7-467ce727c48c.png)|
|:-:|

label をfor属性との組み合わせで検索する例は以下のようになります。

```java
driver.findElement(By.xpath("//label[@for='mng_group_mail']")).click();
```

label が長く部分一致させるパターンです。構文的には 4)～6) と同様になります。

```java
driver.findElement(By.xpath("//label[contains(@for,'説明の一部')]")).click();
```

# 11) linkText で検索

ここからは表示されているテキストで検索するパターンになります。

検索できるような属性もなく、タグ構成も自動生成されたような場合に先へ進む最終手段(?)となりますが、何をテストしているか分からないような気もしてきます。

linkText 検索の例：

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/172826/d0ffb3a8-d812-75f1-0a5b-9c5b4682d235.png)|
|:-:|

テキストを完全一致で検索する場合は以下のようになります。

```java
driver.findElement(By.linkText("保存")).click();
```

改行やコメントを含むテキストの例；

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/172826/89d85d82-9b14-780b-606e-3998eb7922a6.png)|
|:-:|

partialLinkText で部分一致させます。

```java
driver.findElement(By.partialLinkText("VA User1")).click();
```

# 12) テキストで検索

テキスト検索の例：

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/172826/b77d3c32-71f0-ae35-1d77-65aa909043e1.png)|
|:-:|

linkText でも取得できない場合(押下時の動作がjavascriptで記載されている場合など)は、textで取得して押してみます。

```java
driver.findElement(By.xpath("//*[text()=\"PRINT\"]")).click();
```

# その他(補足など)

- 例ではclick メソッドを使っていますが、IEではsendkeysメソッドを使わないと先に進めない場合があります。実際には以下のような感じでブラウザごとに処理を分けることになるかと思います。

```java
if (browser.equals(_BROWSER_IE) || browser.equals(_BROWSER_EDGE)) {
    driver.findElement(By.xpath("//input[@value='OK']")).sendKeys(Keys.ENTER);
} else {
    driver.findElement(By.xpath("//input[@value='OK']")).click();
}
```