ちょっと話題の記事

自動テストはじめませんか?#2

2013.04.26

だいぶ間があいてしまいましたが、seleniumを使った自動テストの続きです。
今回はselenium+PhantomJSについて取り上げたいと思います。

PhantomJSって何?

ブラウザを使わずにJavascriptが実行出来るWebKitベースのツールです。またDOM,CSS,Canvasなどもサポートしています。
PhantomJSだけでももちろん使えますが、今回はseleniumと合わせて使ってみます。(PhantomJSについてはまた別の機会に)

Seleniumで使用するメリットは?

Seleniumのテストを行う際に、問題になる1つとして実行時間があります。IEで実行した場合は特に遅いので時間がかかってしまいます。PhantomJSはWebブラウザを起動するわけではない為、描画処理を必要としない分高速に処理が行われます。

実行環境の構築

今回もEclipse+Java+Mavenを使って動かしてみます。Mavenプロジェクトを作成し、依存関係に以下を追加します。
詳しくは前回の手順を参照して下さい。

[selenium]
グループId:「org.seleniumhq.selenium」
アーティファクトId:「selenium-java」
バージョン:「2.32.0」

[junit]
グループId:「junit」
アーティファクトId:「junit」
バージョン:「4.10」

[GhostDriver]
グループId:「com.github.detro.ghostdriver」
アーティファクトId:「phantomjsdriver」
バージョン:「1.0.3」

また、IEなどを実行するのと同様にドライバが必要なためこちらからダウンロードします。今回はWindows環境のため「phantomjs-1.9.0-windows.zip」ダウンロードし、解凍して「phantomjs.exe」ファイルを任意の場所に置きます。

動かしてみましょう

import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

import org.apache.commons.io.FileUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.phantomjs.PhantomJSDriver;
import org.openqa.selenium.phantomjs.PhantomJSDriverService;
import org.openqa.selenium.remote.DesiredCapabilities;
import static org.junit.Assert.assertEquals;


public class PhantomJSTest {

    private WebDriver driver;
    private String baseUrl;

    @Before
    public void setUp() throws Exception {
        DesiredCapabilities caps = new DesiredCapabilities();
        caps.setCapability(
                PhantomJSDriverService.PHANTOMJS_EXECUTABLE_PATH_PROPERTY,
                "C:\\phantomjs.exe"
        );
        driver = new PhantomJSDriver(caps);

        // htmlの要素が見つからなかったときの待機時間
        driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
        // ブラウザ起動時に開くページ
        baseUrl = "https://www.google.co.jp";
    }

    @After
    public void tearDown() throws Exception {
        // 終了
        driver.quit();
    }

    @Test
    public void test() throws IOException {
        // ここに操作内容を記述する
        driver.get(baseUrl + "/");
        WebElement element = driver.findElement(By.name("q"));
        element.sendKeys("クラスメソッド 会社概要");
        element.submit();
        driver.findElement(By.linkText("会社概要 | クラスメソッド株式会社")).click();

        // ①検証
        assertEquals("会社概要 | クラスメソッド株式会社", driver.getTitle());

        // ②キャプチャをとる
        File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
        FileUtils.copyFile(scrFile, new File("c:\\temp\\screenshot1.png"));

        driver.findElement(By.linkText("ブログ")).click();

        // ウィンドウ切換え
        String parentHandle = driver.getWindowHandle();
        for (String popUpHandle : driver.getWindowHandles()) {
            if (!popUpHandle.equals(parentHandle)) {
                driver.switchTo().window(popUpHandle);
                break;
            }
        }

        // ③検証
        assertEquals("クラスメソッド株式会社 開発ブログ | Developers.IO", driver.getTitle());
    }
}

実行するとgoogleで弊社サイトに遷移し、そこから弊社ブログのリンクをクリックし、ブログページを表示させます。実行してもブラウザが起動する訳ではないので、実際に動いたか分かりません。そこで①検証、③検証でサイトのタイトルを取得しチェックしています。また②キャプチャをとるでサイトのキャプチャをとっています。(ブラウザから起動した場合と同様にちゃんとキャプチャもとれます!)

実行速度の比較

FireFoxと実行速度を比較してみました。
今回のプログラムをそれぞれ数回実行した平均時間は以下のようになりました。

  • FireFox 10.6s
  • PhantomJS 7.9s

これだけのページ遷移ですが既に差が出ていますね。
テスト対象の画面数が多くなると実行時間にかなり差が出てくるかと思います。

まとめ

ドライバを変更するだけでPhantomJSが使えました。キャプチャも撮れるし、速度も速いしブラウザがいちいち起動しないので、とても便利なツールかなと思います。
ただし、キャプチャをとったときの見た目は実際のブラウザ(IEなど)とは違ってきますし、javascriptの挙動も違ってくる場合があるので各ブラウザからのテストは省略できないかと思います。
よって定期的なテストではPhantomJSを使用し、最終的な確認ではブラウザからのテストを実施するといった使い方が効果的なのではないかと思います。