XPathのあれこれ for テスト自動化

# Outline

UIのテスト自動化ではxpathが主役になる。
オブジェクトを特定するとき、基本的にxpathでlocationを特定し、クリックしたり、検証したりするからである。
T-DASHやRanorexといったローコードのテスト自動化では、オブジェクトを自動で取得する機能が備わっている。
しかし、オブジェクトによっては、正しく取れない場合がある。
例えば
- 単純にテスト自動化ツールで、一意にとれない
- アクセスの都度、動的なIDが割り振られるXPath
- index番号で構成されたXPathで、ＵＩの変更が起きるもの
- データドリブンでテストするため、対象のテキストがテストデータによって変わってしまう
- 表で、行・列のヘッダ名は固定だが、そのヘッダ名の位置が変更される

この場合、XPathを手動でとる必要がある。
ここでは、XPathの取り方、ちょっとしたテクニック等を記載する

# XPathの取り方の基本

今回、ChromeのDeveloperToolで説明する。

Chromeを起動して対象のページに遷移後、DeveloperToolを起動する。windowsであれば、F12を押す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/c9a3daff-bdbb-5f64-9026-ddcad8de0d2f.png)

次に、inpsectのボタン（下図の①）を押す。（もしくは CTRL + SHIFT + c）
すると、左のページにマウスを移すと、エリア選択できるようになる。
そこでXPathをとりたいオブジェクトをクリックする（下図の②）。
その結果、DevelopetToolのElementsで対象のHTMLが選ばれる（下図の③）


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/84185f0c-0a87-bc33-7625-5e15898977e9.png)

選ばれたHTMLにマウスをあわせ、右クリックする。
メニューがでてくるので、Copy -> Copy XPath を選ぶ（下図の④）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/2e2d4ff9-4571-275f-cce7-66c78e56ca03.png)

最後にcopyしたXPathが正しく、一意に特定されているかを確認する
Elementsのなかでマウスクリックし、 CTRL + f をクリックする。
すると、XPathの検索ができる（下図の⑤）
検索の結果、希望しているHTML要素であるかを確認すること、一意に特定（検索HIT数が１）されていることを確認することができる。
ここで取得されたものがXPathである。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/0bc862b2-2ffb-59af-63f0-1e63baa469e2.png)


今回用いたサイトはこちら
https://grp01.id.rakuten.co.jp/rms/nid/vc?__event=login&service_id=top

今回希望したHTMLは
```
<input type="text" name="u" maxlength="100" size="25" value="" class="textBox" id="loginInner_u">
```

今回取れたXPathは
```
//*[@id="loginInner_u"]
```
これは、”任意のHTMLタグでidがloginInner_uである要素”と意味する。

DeveloperToolでとれた値以外に、以下のXPathでもこのHTMLを特定することは可能である
```
//input[@id="loginInner_u"]
```
意味：inputタグでidがloginInner_uである要素

```
//input[@name="u"]
```
意味：inputタグでnameがuである要素

これが、基本的なXPathの取り方である

# index番号の構成で、ちょっとしたUI変更で修正が発生する

今回のサイト
https://keiba.rakuten.co.jp/

今回、ヘッダーメニューにある、”出馬表”（下図の①）のXPath（下図の②）をとってみる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/1756c5e6-c785-2c2b-329c-ebf62f2e38cc.png)

XPathをcopyした結果が以下のとおりである
```
/html/body/div[2]/div[4]/div/ul/li[2]/a
```

これはどういう意味をあらわしているかというと、
下図のようにHTMLのタグの階層、同じタグが含まれてる場合何番目のタグかを示している。

今回は、”html -> body -> ２番目のdiv -> ４番目のdiv -> （任意の）div -> （任意の）ul -> 2番目のli -> （任意の）a ”　で、”出馬表”のlocationを定義している。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/80a134fb-f5c5-b3e9-a1e6-73914c3c78c8.png)

この場合、ヘッダーメニューの位置が下図のように変更になったりすると（/html/body/div[2] -> /html/body/duv[3] ）たちまち、XPathが特定できなくなってしまう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/6e7849b0-babd-509e-e565-6fc41a533427.png)

そのため、XPathを手動で取得して、最適化したほうが良い時もある。

今回、手動で定義したXPathはこちら（あくまで一例である）

```
//div[@class="glonavsub"]//ul/li/a[contains(text(),"出馬表")]
```

今回のXPathの定義した理由を説明する

```
//div[@class="glonavsub"]//ul/li/a
```
この定義はdivタグでclassがglonavsubの要素を特定します。
これはトップ、出馬表～　のヘッダーメニューの部分に該当します。
次に、ul/li/a の要素を特定します
これは複数HITします。出馬表のメニューを選びたいため、a[2]としてもよいのですが、メニュー順番が変更しても特定できるように、”出馬表”の文字列が含まれるaタグとして指定しておくと、将来的に変更に強いXPathになる。そこで、以下のように定義する

```
//div[@class="glonavsub"]//ul/li/a[contains(text(),"出馬表")]
```


# 表で行・列のヘッダ名を指定した要素をとりたい

## 列の名前を指定する場合

表で、列の要素にランダム性があるとする
以下の図では、色の列は現在３番目だが、表をカスタマイズでき、４番目に変わる可能性があるとする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/ac53d10b-be3e-efdf-2f47-2f1929fc0d2d.png)

単純に、チャーハンの色のXPathをとると以下のようになる。
４行目(tr[4])、３列目(td[3])を指している。
この場合、色の列が４列目に変わった時に、”赤”が取れなくなる。

```
/html/body/table/tbody/tr[4]/td[3]
```


では、色の列を常にとるにはどうしたらよいか？以下のようにして特定できる
```
/html/body/table/tbody/tr[4]/td[count(//table[@name="table1"]/tbody/tr/th[text()="色"]/preceding-sibling::th)+1]
```

これはいったい何を示しているのだろうか
まずtdのなかで指定している計算式
```
count(//table[@name="table1"]/tbody/tr/th[text()="色"]/preceding-sibling::th)+1
```
これは値は3になる。

下図①の、表のヘッダにあたる部分から、”色”のthタグがtrの中で何番目であるかをまず調べる。
ただし、”食べ物”が0番目に該当するため、 +1をしている。


次に、チャーハンの行が４番目であるため、tr[4]で指定する
その次のタグtdで、先ほど取得した、現在”色”のある列数をしていすると、チャーハンの色の列を特定できる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/1a2f5081-aebd-bf6e-5ef0-c03be1d312d2.png)


## 行の名前を指定する場合

次は、行のラベルを指定したい場合。
以下の図では、京都の行を常に指定したい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/819224f6-991a-fe7b-0945-14c8ee181481.png)

単純に京都の3Rの”出馬表”を取得すると、以下のようになる
```
/html/body/p/table/tbody/tr[3]/td[3]
```

必ずしも”京都”の行が３行目(tr[3])でないとする。
その場合のXPathは以下のようになる。
```
/html/body/p/table/tbody/tr/th[text()="京都"]/../td[3]
```

これは、まず京都の要素を特定します（下図①）。
その後、一つ上の階層つまり京都の行を指定（下図②）、最後にtdの３番目を指定する（下図③）
このような流れで特定する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/9b00081b-f2c8-b030-a218-dfaf9a50a5a1.png)

# T-DASHでxpathの取り方

T-DASHはローコードのテスト自動化ツールである
T-DASHも基本的に、XPathをベースにオブジェクトを特定し、テスト操作を行う。

https://service.valtes.co.jp/t-dash/


T-DASHには、WEBアプリケーション、windowsアプリケーション両方に対してxpathを簡単に取得する機能が備わっている。
それをここでは紹介する。
ただ、上記のような課題はT-DASHで自動取得したxpathで解決できない可能性があります。
その場合は、DeveloperToolを用いで改めてxpathを取得する必要があります。


## WEB アプリケーション

画面キャプチャツールがある

トラッキング機能を用いると、下図のように、黄色いフォーカスエリアが表示され、xpath取得したい場所を選択すると、xpathが取得される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/0aa48ac8-61df-2040-45b3-85cb7d9b72de.png)

また、パス取得実行機能を用いると、ある程度自動でxpathを取得してくれる。


1.要素名を入力する（メールアドレス、パスワード、ログイン）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/103a0a18-8495-baad-0689-e680abbc96c1.png)
2.パス取得実行をクリックする　→　それぞれの要素を推測して、自動でxpathが取得される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/3bdf044f-535d-2a19-4b83-bd6acaa75fe3.png)

## Windowsアプリケーション

T-DASH wintoolがある

対象のエリアをクリックすると、要素Xpathを取得される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/355baff9-1a87-f69c-76b6-f2a680b57284.png)



# 参考記事

https://webbibouroku.com/Blog/Article/xpath

https://qiita.com/rllllho/items/cb1187cec0fb17fc650a