きり丸の技術日記

技術検証したり、資格等をここに残していきます。

XPathで親要素にさかのぼって検索する

Seleniumを含めたE2Eツールでは、XPathで指定できると動作が安定します。

今回の記事では、XPathで親要素を検索する方法を記載します。

概要

../と記載すると、指定したDOMより親の要素を検索できます。

この記事では、次のXPathを導きます。

//td[contains(text(), 'Java')]/../td[2]

ゴール

  • XPathにて子孫を検索する
  • XPathにてDOMの親要素を検索する
  • XPathにて記載されている文言を検索する
  • XPathにて複数ヒットしたときに目的のDOMを指定する

今回は、GitHubに記載しているプロフィールを利用します。言語と経験年数が記載されているDOMから、言語(Java)を指定すると経験年数(7年)のDOMを指定できるようにします。

f:id:nainaistar:20210907204416p:plain

ソースコードを見ればわかりますが、要素にはIDやClass等の属性は付与されていません。

<table>
<thead>
<tr>
<th>言語</th>
<th>年数</th>
</tr>
</thead>
<tbody>
<tr>
<td>Java</td>
<td>7年</td>
</tr>
<tr>
<td>VB6</td>
<td>1.5年</td>
</tr>
</tr>
</tbody>
</table>

環境

  • Windows
    • Chrome

対応

子孫を検索する

//と記載すると子孫要素を検索できます。

ルート要素の省略で書くことが多いのですが、中間の要素の省略で書いてもよいです。少々複雑になるため、「他のユースケース」で紹介します。

DOMの親要素を検索する

../と記載すると、親要素をたどれます。

今回の場合、言語を検索した結果のDOMは<td>Java</td>を取得できます。経験年数に至るには1度親要素のtrタグにたどってから、tdの2番目要素を検索することで経験年数の<td>7年</td>を取得できます。

<tr>
<td>Java</td>
<td>7年</td>
</tr>

記載されている文言を検索する

*[text() == 'Java']とすることで、表示している文言を元に「Java」という文言でDOMを検索できます。ただ、半角スペース等が前後に入っていると検索できません。

*[contains(text(), 'Java']とすると、半角スペースが前後に入っていても検索できます。ただ、条件が緩い検索になりますので、確実に指定できることを確認しましょう。

複数ヒットしたときに目的のDOMを指定する

[n]と記載することで、複数件がヒットする条件のうち、N番目のDOMを指定できます。

注意事項として、子孫を検索する記法と一緒に使用しているとき、[n]番目を指定しても検索できません。動作確認はしっかりしましょう。

[1]を指定しているのに、複数件ヒットするケース。[2]と指定すると1件もヒットしない。

f:id:nainaistar:20210907204432p:plain

まとめ

記載したことをまとめると次のXPathを導けます。

XPath:

//td[contains(text(), 'Java')]/../td[2]

  • //で子孫要素を検索できるようにする
  • td[contains(text(), 'Java')]でJavaと表示しているtdタグを検索する
  • ../でtdタグから親要素のtrタグを取得する
  • td[2]で2番目のtdタグ(経験年数)を取得する

他のユースケース

GitHubのリポジトリページにて特定のリポジトリのStarをクリックしたい。というユースケースです。

今回は、私のリポジトリのLeetCodeリポジトリのstarボタンを指定する、という前提でXPathを指定します。

Xpath:

//a[contains(text(), 'LeetCode')]/../../../..//button[@value="Star"]

  • リポジトリ名はaタグで取得できます。
  • starボタンと同一の要素までさかのぼる必要があるため、4回親の要素をさかのぼる必要があります。
  • ボタンの要素までは省略したいので//で省略します。
  • 表示上のボタンはStarだけですが、裏にUnstarのボタンもいますので一意になる属性を与えます。

f:id:nainaistar:20210907204820p:plain

終わりに

親要素にさかのぼることができれば、たとえボタン自体に一意に特定できるような属性が付与されていなくても、周辺情報を元に一意に特定できます。

そもそもIDやClass等で一意に特定できれば問題はありませんが、画面を作成しているチームとE2Eテストを行うチームが別であるパターンもあります。XPath力を鍛えることで柔軟にテストできますので、ぜひ覚えてみてください。

まぁ。ここまで工夫してしまうと、ちょっとでも要素が崩れたときに運用コストが跳ね上がるんですけどね…。悩ましいところです。


この記事がお役に立ちましたら、各種SNSでのシェアや、今後も情報発信しますのでフォローよろしくお願いします。

参考情報

f:id:nainaistar:20210907204126p:plain