LoginSignup
73
71

More than 5 years have passed since last update.

SeleniumでChromeのデベロッパーツール相当の機能を使ってみよう

Last updated at Posted at 2014-12-12

この記事はSelenium/Appium Advent Calendar 2014の12日目の記事です。誰も書かなさそうなので小ネタを引っ張りだしてきました。

chromedriverのアーキテクチャ

chromedriverはJSON Wire Protocolを受けるSelenium ServerとChromeの間の通信をRemote debugging protocolで行っています。これは、Chromeに標準で内蔵されているDeveloper Toolsでも利用しているものです。

chromedriverを使ったプログラムを途中で止めて、Developer Toolsでデバッグしてみて、そのDeveloper Toolsを閉じずに、プログラムを再開したら、Seleniumのセッションが使えずに死ぬといった経験はわかる人にはわかるでしょう。これは、両者が同じAPIを利用していて、かつそのAPIのセッションが同時には使えないことに起因します。

同じAPIを利用しているということは、Developer Toolsでできそうなことってたいていchromedriverでできそうですよね?ということで、Developer Toolsの以下の機能について試してみました

  • mobile emulation
  • console logの取得
  • Performance Logの取得

mobile emulation

モバイルWeb開発では大活躍のmobile emulation機能です。Developer Toolsでは携帯電話っぽいアイコンを押すだけで表示がスマホのものになります。この機能はchromedriver2.11から利用可能となっています。

これをchromedriverから利用するのは、capabilityを適切に設定してやるだけです。
以下にrubyの例を書きます。

require "selenium/webdriver"

mobile_emulation = { "deviceName" => "Google Nexus 5" }
chrome_options = { "chromeOptions" => { "mobileEmulation" => mobile_emulation } }
caps = Selenium::WebDriver::Remote::Capabilities.chrome(chrome_options)

driver = Selenium::WebDriver.for :chrome, desired_capabilities: caps
driver.get "https://twitter.com"
puts driver.current_url #=> "https://mobile.twitter.com/"

その時のスクリーンショットはこんな感じになります。twitterのモバイル版の画面が表示されていることや、ブラウザのウインドウサイズとは別にGoogle Nexus 5相当の画面サイズでレンダリングされていることがわかると思います。

スクリーンショット

今回 capabilitiesとしてdeviceNameを直指定しましたが、これは、deviceMetrics(width, height, pixelRatio)およびuserAgentを指定するようなやり方もあります。

mobile_emulation = {
  "deviceMetrics" => { "width" => 360, "height" => 640, "pixelRatio" => 1.0 }
  "userAgent" => "xxxx",
}

touchイベントも起こせます。以下のように、single_tapすることができます。ただし、double_tapやlong_pressは、chromedriverが未対応なのでできないようです。

driver.extend Selenium::WebDriver::DriverExtensions::HasTouchScreen

driver.get "https://s3-ap-northeast-1.amazonaws.com/codegrid/touch-click-pointer/demo/01-trytouch/index.html"
area = driver.find_element(:css, "#hitarea")
driver.touch.single_tap(area).perform

codegrid さんのサンプルサイトを使っています

console logの取得

以下の例では、browserのログ(要はconsoleに出るやつ)を設定して、javascriptのエラーを検知するようにしています。chromedriverはlogginPrefsに対応しておりますが、多分デフォルトはOFFになっているので、設定しないと何も取得できません。

この例では、内藤薬局でjavascriptのエラーが出ていることのログが取得できます。

log_prefs = { "browser" => "ALL" }
caps = Selenium::WebDriver::Remote::Capabilities.chrome("loggingPrefs" => log_prefs)

driver = Selenium::WebDriver.for :chrome, desired_capabilities: caps
driver.get "http://hm.aitai.ne.jp/~naitonet/"
p driver.manage.logs.get(:browser).first
#=> #<Selenium::WebDriver::LogEntry:0x007ff6da15f968
 @level="SEVERE",
 @message="http://hm.aitai.ne.jp/~naitonet/ 998:18 Uncaught TypeError: Cannot set property 'left' of undefined",
 @timestamp=1418304232408>

また、同じような感じで画像のリンク切れも検出できます。

driver.get "http://homepage3.nifty.com/TOKU/"
p driver.manage.logs.get(:browser).first
#=> #<Selenium::WebDriver::LogEntry:0x007ff6db85de08
 @level="SEVERE",
 @message=
  "http://www.noe.jx-group.co.jp/csr/click/images/click_bn01.gif 0:0 Failed to load resource: the server responded with a status of 404 (Not Found)",
 @timestamp=1418304578471>

これをうまく使えば、javascriptのミスや画像のリンク切れみたいなものの検出がより効率的になります。

Performance Logの取得

同様にPerformance Logも取得できます。

log_prefs = { "performance" => "ALL" }
caps = Selenium::WebDriver::Remote::Capabilities.chrome("loggingPrefs" => log_prefs)

driver = Selenium::WebDriver.for :chrome, desired_capabilities: caps
driver.get "http://azcji.cocolog-nifty.com/blog/cat1459704/index.html"
driver.manage.logs.get(:performance) #=> たくさん出る!

要はChromeのNetworkとかTimelineに出てくるような情報が取得できます。これを使ってブラウザのパフォーマンス測定の自動化をしようとするとそれだけでヒトネタになると思うのでここの詳細はまた別の機会にしたいと思います。

まとめ

こういうエントリー書こうと重いサイトとか画像リンク切れのサイトとか変なjsのサイトとか探そうとすると案外難易度高かったりするのですね。。

明日のSelenium/Appium Advent Calendarはまだ立候補者がいないので、誰か是非ともよろしくおねがいします!

73
71
0

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
73
71