LoginSignup
15
14

Seleniumのcss locatorの話

Last updated at Posted at 2015-12-12

Selenium/Appium Advent Calendar 2015 12日目です。

薄い話が面白くてしょうがないです。

2013年のAdvent CalendarSelenium の locator とうまくつきあうための話を書きました。この話自体は2年経ったいまでも全然有効な話なのですが、追加でcss selectorについて掘り下げていきたいと思います。

Seleniumのlocatorの話

Seleniumのlocatorとしてはこれを使うべきという指針は、おおざっぱにいうとこんな感じでした。

  • formではname属性を使う
  • それ以外は基本css selectorを使う

css selectorに関してはこういうselctorがあるよという程度の紹介で、何を使うべきというのは語られていませんでした。

css selectorの中の優先度

具体的にどのようなselectorを使うかという話の前にもう少し抽象的な話をします。個人的な考え方として、以下の優先度で要素を特定できるようにするのがよいと思います

  • ドキュメントのuniqueな識別子を利用するようなcss selector
  • ドキュメントのセマンティクスを元に特定できるようなcss selector
  • その他

はい何を言っているかって感じがしますね。

なお、本文書の主題としては、ドキュメントのuniqueな識別子をどう設計するかという話なので、セマンティクスに関してはふれません。どうせmicrodataとかをきちんと考えてセマンティクスに設計されたサイトなんて本当限られているわけですし。

uniqueな識別子とは

要はそのドキュメント(html)の中で一意に要素を特定するためのものです。典型的には、htmlのid属性というのはそのような用途に使うためのものです。

id属性はもともとそのような性質があるので、理解は速いですが、class属性だってそのように利用できます。要は、class属性に入れる値が、ドキュメントの中でuniqueになるようにすればいいのです。

<a href="/" class="link_to_top">top</a>

例えば上記のような感じです。上のclass属性はid属性であっても違和感がないとは思います。(じゃあclass属性じゃなくてidでいいじゃんって思うかもしれないですが、なんらかの事情でidには本当にuniqueでかつシステム的な値が入ることがありますし)

要はclass属性でもなんでもよいのですが、何らかのわかりやすいuniqueな識別子が事前にわかっていれば、テストからその要素をuniqueに扱えるということです。

uniqueな識別子を取り決める

事前にわかっているためには、テストを書く人と開発する人で事前にインターフェースとして取り決める必要があります。実はSeleniumのテストを書く上で重要なのはこういったコミュニケーションやプロセスをきちんと設計できるかどうかであったりします。

これまではこのようなuniqueな識別子利用するにはid属性やclass属性を使うことが一般的でした。しかし、id属性やclass属性はフロントエンドの実装においても重要な要素だったりするので、しばしば開発とテストでの競合が起きることもありました。(つまり、テストを書く人が安易に属性を追加しにくい状況が生まれてしまうのです)

カスタムdata属性を使う

そこで、最近お薦めているのがカスタムdata属性です。カスタムdata属性とはdata-*で始まるドキュメントに固有の独自データを格納することを想定した属性です。例えば、data-test-idみたいなカスタム属性に識別子をいれておけば、

<a data-test-id="link_to_top">top</a>

a[data-test-id='link_to_top'][data-test-id='link_to_top']というようなcss selectorで取得できるようになります。

事前にどういう名前の属性を使うかを決めておきさえすれば、その属性を自由にテストを書く人が追加でき、それがアプリケーションに影響を与える可能性は極めて低くなります。

Capybaraで独自セレクタを登録する

uniqueな識別子として、カスタムdata属性をインターフェースとして取り決めたのですが、毎回上記のようなcss selectorを書くのはだるいです。link_to_topのような指定だけで済むようにしたいです。

例えば、RubyでCapybaraを使ってSeleniumのテストを書いているのであれば、Capybaraで以下のように独自セレクタを実装し、findで利用できるようになります。

Capybara.add_selector(:data_selector) do
  css { |type| "[data-test-id='#{type}']" }
end

find(:data_selector, "link_to_top").click

なお、Capybara.default_selectorを設定しておけば、以下のようにもかけます。

Capybara.default_selector = :data_selector
find("link_to_top").click

まとめ

文中でも書きましたが、Seleniumのテストを書く際に重要なのは、テストを書く人と開発する人で協力できるような、体制プロセスを構築し、テストとテスト対象の間でのインターフェースをきちんと設計することです。

そのために、開発に影響がでにくいようなカスタムdata属性を使っていくのが、協力体制を維持継続していくためにも便利なのではと思っています。

それでは楽しいSeleniumライフを。

明日は@naoqoo2さんです。

15
14
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
14