モダンな Selenium でスクリーンキャプチャ/スクリーンショット (Screen capture / Screen shot)方法

先日、Selenium でキャプチャ取る方法を聞かれたのでまとめる。
ぐぐってもモダンな方法が出てこないので。


結論を言うと、Selenium RC 0.9.2 (Core にも入ってた) から導入された、captureScreenshot を使うか、導入時期不明だけど、最新の Selenium 1.0 Beta 2 には入っている captureEntirePageScreenshot を使う。関連する API として、RC の Java Client には captureEntirePageScreenshotToString などもあるので興味のある人は、doc を見ると良い。


captureScreenshot と captureEntirePageScreenshot の違いはデスクトップ全体をキャプチャするか、テストしているページだけをキャプチャするかの違い。


captureEntirePageScreenshot のほうがテストしているページだけキャプチャできるので、良いように思えるが若干の制限がある。


Browser Luncher が *iexplore ではキャプチャできない。ちなみに、Selenium 1.0 Beta 2 のときに「*iexplore」の扱いが変更になった点に注意。デフォルトが Internet Explorer in HTA mode になった。
http://clearspace.openqa.org/community/selenium/blog/2009/01/13/selenium-rc-beta-2-goodies-and-gotchas


IE で、captureEntirePageScreenshot を動かしたいときは、まず、IE に、snapsIE (http://snapsie.sourceforge.net/)という selenium 用に開発されてる ie で screen capture を撮るライブラリをアタッチする。僕の環境では以下の通りで実行できた。実行できない人は上記サイトを参考に。

  1. 上記サイトから snapsIE のファイルをダウンロード
  2. 解凍してできた DLL を C:\Windows に置く
  3. コマンドプロンプトなどで、「regsvr32 Snapsie.dll」を実行


で、non HTA mode である *iexploreproxy で Selenium RC Client を起動してキャプチャを撮る。


具体的なコードとしては、例えば Java であれば 以下のような Selenium RC Clinet (+ JUnit4) のコードで行う。Path に関しては色々ためしたのだが、captureScreenshotはファイル名だけ書くと Selenium RC Server 側の起動ディレクトリ以下にファイルをキャプチャしてくれる。captureEntirePageScreenshot は絶対パスでないとダメ。この辺りは、マルチプラットフォームでテストするときには、ポイントになりそう。


余談だが、モダンでない capture 方法として、Java だったら、java.awt.Robot を使ってキャプチャを行うという方法もある。


GoogleJavaTest.java

import com.thoughtworks.selenium.*;
import org.junit.Test;
import org.junit.After;
import org.junit.Before;
import static org.junit.Assert.*;

public class GoogleJavaTest {
    private Selenium browser;

     @Before 
    public void setUp() {
        browser = new DefaultSelenium("localhost",
            4444, "*iexploreproxy", "http://www.google.com");                              // (1)
        browser.start();
    }

    @Test
    public void testGoogle() {
        try {
            browser.open("http://www.google.com/webhp?hl=en");
            browser.type("q", "hello world");
            browser.click("btnG");  
            browser.waitForPageToLoad("5000");
            assertEquals("hello worl - Google Search", browser.getTitle());
        } catch (AssertionError ex) {
            browser.captureEntirePageScreenshot("C://tmp/errorTestGoogleEntire.png", "");  // (2)
            browser.captureScreenshot("C://tmp/errorTestGoogle.png");                      // (3)
            throw ex;
        }

    }

    @After
    public void tearDown() {
        browser.stop();
    }
}

ruby の場合は以下の通りで実行できる。また、試してないが、RSpec のほうには、capture_html_snapshot という現在の html 全体を取得できそうなメソッドがあった。

require "test/unit"
require "selenium/client"

class GoogleTest < Test::Unit::TestCase
  attr_reader :browser

  def setup
    @browser = Selenium::Client::Driver.new "localhost", 4444, "*firefox", "http://www.google.com", 10000
    browser.start_new_browser_session
  end

  def teardown
    browser.close_current_browser_session
  end

  def test_page_search
    begin
    browser.open "/"
      assert_equal "Google", browser.title
      browser.type "q", "hello world"
      browser.click "btnG", :wait_for => :page
      assert_equal "hello worl - Google Search", browser.title
    rescue Test::Unit::AssertionFailedError => e
      browser.capture_entire_page_screenshot "C://tmp/errorTestGoogleEntire.png", ""
      browser.capture_screenshot "C://tmp/errorTestGoogle.png"
      raise e
    end
      
  end

end


TODO:Mac OS XLinux 系でも試す。
一応、HTML Selence でも上記動くと思うので、Selenium IDE でも captureScreenShot のコマンドを使えばできると思う。後で試す。