読者です 読者をやめる 読者になる 読者になる

Seleniumでテストしたページのキャプチャを撮る+画像を全部保存する

http://d.hatena.ne.jp/wonodas+dev/20121129/1354163496 の続き

前回のでもできるはできるのだが、今回の場合

  1. セッションが変わるとログインページに戻ってしまう
  2. imgのsrcに入っているタグが*.jpgなどの形式ではなくURL

file_get_contentsは新しくセッション作ってページの内容を取得するらしく、やれどもやれどもログイン画面のソースコードしか手に入らなかった。んで、しょうがないのでjavascriptを駆使することに…
あとグラフを描画させているんだが、サーバでグラフ画像作って貼り付ける形式ではなくクライアントサイドで描画させる方式のため、img src="URL"のURLで(jpg|png|gif)が含まれないことが判明(先にわかっとけ)。これを取得する方法はなさげなのでとりあえずURL表示させてキャプチャという強引な方法を取ることにしました。

SeleniumではgetEvalまたはrunScriptでjavascriptコードを走らせることができます。

VerifyTestCase.phpに追加

<?php
class PHPUnit_Extensions_VerifyTestCase extends PHPUnit_Extensions_SeleniumTestCase
{
     //中略
    //指定したURLを開いてスクリーンショットを取る(クライアントサイドで生成した画像)
    public function captureImageFromUrl($url, $dir = null, $fileName = null)
    {
        if($dir == null ){
            $dir = __DIR__;
        }
        
        if($fileName == null){
            $fileName = date("Ymd_His");
        }
        
        $this->open($url);
   //余計なのをうつさないために(twitterとかね)最大化しておく
        $this->windowMaximize();
        $this->captureScreenshotAndWait($dir . "/image" . $fileName . ".png");
    }
    
    //現在のページのスクリーンショットを撮る
    public function captureCurrentPage($dir = null , $fileName = null){
        if($dir == null ){
            $dir = __DIR__;
        }
        
        if($fileName == null){
            $fileName = date("Ymd_His");
        }
   //余計なのをうつさないために最大化しておく
        $this->windowMaximize();
        //file名を指定していない場合はimage-Ymd_Hisというファイル名で保存される
        $this->captureScreenshotAndWait($dir. "/image-". $fileName. ".png");
    }

    //URL指定したページのイメージを取得する(jpg, gif, pngだけ)
    public function saveImageFromUrl($url, $dir = null)
    {
        if($dir == null) {
            $dir = __DIR__;
        }
        
        if (preg_match("/(jpg|gif|png)$/i", $url)) {
            //画像のファイル名で保存する
            file_put_contents($dir . "/" . basename($url), file_get_contents($url));
        }
    }

    //ページ内の画像をすべて保存する
    public function saveImagesOnPage($url, $dir = null)
    {
        $this->open($url);
        //今表示しているページのdocumentを取得
        $this->getEval("doc=this.page().getCurrentWindow().document;");
       //imgタグを全部取得
        $this->getEval("imageArr = Array.slice(doc.getElementsByTagName('img'));");
        //imgタグがいくつあるかをimgCountに格納
        $imgCount = $this->getEval("imageArr.length;");

        //なかったら終わる
        if ($imgCount == 0) {
            return;
        }

        $dir = $dir === null ? __DIR__ : $dir;
        $dirPath = $dir . "/" . date("Ymd_His");
        mkdir($dirPath);

        $imgUrlArr = array();
        for ($i = 0; $i < $imgCount; $i++) {
            //imgのsrcを取得して配列に詰める
     //なぜかgetEval("i=0");getEval("iamgeArr[i].src");getEval("i = i+1");だと最初しか取れないのでこうした
            $imgUrlArr[] = $this->getEval("imageArr[" . $i . "].src;");
        }

        //重複はのぞく
        $imgUrlArr = array_unique($imgUrlArr);

        foreach ($imgUrlArr as $index => $url) {
            //jpg,gif,pngだったら画像を保存、そうじゃなかったらキャプチャ(二重チェックになってるなこれ…)
            if (preg_match("/(jpg|gif|png)$/i", $url)) {
                $this->saveImageFromUrl($url, $dirPath);
            } else {
                $this->captureImageFromUrl($url, $dirPath, $index);
            }
        }
    }
}