PhantomCSSでViewの回帰テスト


https://github.com/Huddle/PhantomCSS 

![example](https://raw.github.com/Huddle/PhantomCSS/master/readme_assets/intro-example.png)
(画像は本家より)


PhantomCSSはJavaScriptでViewの回帰テストができるフレームワーク。上の画像のように異なっている部分をピンク色で表示してくれる。
今回、OSはMacを想定しているが、Windowsとかでも使えるみたい。


## 準備

使用するためにはPhantomJSとCasperJSが必要なのでインストール。

```bash
brew update
brew install phantomjs
brew install casperjs --devel
```


ちなみに何も考えずに `brew install casperjs`としたら`1.0.4`がインストールされ以下のメッセージが出てダメだった。

```
CasperJS 1.0.x does not support PhantomJS version >= 1.9
```

CasperJS本家にもこの問題が記述されていて1.1系列のインストールを推奨している。

http://casperjs.readthedocs.org/en/latest/installation.html


## PhantomCSSを使ってみる

まずはソースコードをクローン。

```bash
git clone git@github.com:Huddle/PhantomCSS.git
```


とりあえずデモを試してみる。


```bash
$ casperjs test demo/testsuite.js
Test file: demo/testsuite.js                                                    

Must be your first time?
Some screenshots have been generated in the directory ./screenshots
This is your 'baseline', check the images manually. If they're wrong, delete the images.
The next time you run these tests, new screenshots will be taken.  These screenshots will be compared to the original.
If they are different, PhantomCSS will report a failure.
WARN Looks like you didn't run any test.                                        
```

ふむふむ。
前回の結果と比べるテストなのか。

この時、以下の4つの画像が作成されていた。

- screenshots/cappuccino success_2.png
- screenshots/coffee machine close success_3.png
- screenshots/coffee machine dialog_1.png
- screenshots/open coffee machine button_0.png

4つ生成されるのはテストケースが4つあって(正確にはスクリーンショットを取るタイミングが4回で`phantomcss.compareAll()`している)、例えば以下のように指定しているから。

```javascript:demo/testsuit.js
phantomcss.screenshot('#myModal', 'coffee machine dialog');
```

それでは、もう一回テストを走らせてみる！

```bash
$ casperjs test demo/testsuite.js
Test file: demo/testsuite.js                                                    


PASS No changes found for screenshot ./screenshots/cappuccino success_2.png


PASS No changes found for screenshot ./screenshots/coffee machine close success_3.png


PASS No changes found for screenshot ./screenshots/coffee machine dialog_1.png


PASS No changes found for screenshot ./screenshots/open coffee machine button_0.png

PhantomCSS found 4 tests, None of them failed. Which is good right?

If you want to make them fail, go change some CSS - weirdo.
PASS 4 tests executed in 4.636s, 4 passed, 0 failed, 0 dubious, 0 skipped.      
```

この時は、以下の4つの画像が新たに作成される。

- screenshots/cappuccino success_2.diff.png
- screenshots/coffee machine close success_3.diff.png
- screenshots/coffee machine dialog_1.diff.png
- screenshots/open coffee machine button_0.diff.png

今回はViewに変更がなかったのでテストが通ったようだ。

ここで、デモ用のHTMLのCSSを適当に変更：

```diff:demo/coffeemachine.html
			.mug {
- 				font-size: 180px;
+ 				font-size: 150px;
				color: #666;
			}
```

この上で、テストを再実行！

```bash
$ casperjs test demo/testsuite.js
Test file: demo/testsuite.js                                                    


FAIL Visual change found for screenshot ./screenshots/cappuccino success_2.png (29.07% mismatch)
#    type: fail
#    file: demo/testsuite.js
#    subject: false


PASS No changes found for screenshot ./screenshots/coffee machine close success_3.png


FAIL Visual change found for screenshot ./screenshots/coffee machine dialog_1.png (20.67% mismatch)
#    type: fail
#    file: demo/testsuite.js
#    subject: false


PASS No changes found for screenshot ./screenshots/open coffee machine button_0.png

PhantomCSS found 4 tests, 2 of them failed.

PhantomCSS has created some images that try to show the difference (in the directory ./failures). Fuchsia colored pixels indicate a difference betwen the new and old screenshots.
FAIL 4 tests executed in 6.553s, 2 passed, 2 failed, 0 dubious, 0 skipped.      

Details for the 2 failed tests:

In demo/testsuite.js
  Untitled suite in demo/testsuite.js
    fail: Visual change found for screenshot ./screenshots/cappuccino success_2.png (29.07% mismatch)
In demo/testsuite.js
  Untitled suite in demo/testsuite.js
    fail: Visual change found for screenshot ./screenshots/coffee machine dialog_1.png (20.67% mismatch)
```

この時新たに作成されるファイルは以下の4つ

- failures/cappuccino success_2.fail.png
- failures/coffee machine dialog_1.fail.png
- screenshots/cappuccino success_2.fail.png
- screenshots/coffee machine dialog_1.fail.png

更に、以下の2つは変更されている

- screenshots/cappuccino success_2.diff.png
- screenshots/coffee machine dialog_1.diff.png

## 各画像の意味

### 初回のスクリーンショット [screenshots/filename.png]

coffee machine dialog_1.png
![coffee machine dialog_1.png](https://qiita-image-store.s3.amazonaws.com/0/6664/662e2b3c-c76a-8e09-8705-7dae4622876e.png "coffee machine dialog_1.png")


### 2回めのスクリーンショット [screenshots/filename.diff.png]

coffee machine dialog_1.diff.png
![coffee machine dialog_1.diff.png](https://qiita-image-store.s3.amazonaws.com/0/6664/9c95b654-4a2c-3b9f-161b-3fb6da16b916.png "coffee machine dialog_1.diff.png")


### 初回と2回めの違い [screenshots/filename.fail.png] [failures/filename.fail.png]

coffee machine dialog_1.fail.png
![coffee machine dialog_1.fail.png](https://qiita-image-store.s3.amazonaws.com/0/6664/d61f0880-1fec-a887-8ad1-b0c8858a3e99.png "coffee machine dialog_1.fail.png")

これは違いがあった場合のみ生成される。今回はMagのロゴのサイズを小さくしたのでこんな感じでDiffが出ている。単純な画像の比較なので上部が変更されると下も全部変わったと判断されている。
なお、`screenshots/`下と`failures/`下の2つのファイルの中身は同じだった。

## 所感

PhantomCSSは色々カスタマイズできるが、基本的には

***「JavascriptでViewの一部の要素が変化していないかテストしたい」***

時のライブラリみたい。

自分は元々はRailsで生成したページに対しページトータルでのViewの回帰テストをしたかったのだが、JSで画像の比較をするライブラリはCanvasベースの[Resemble.js](http://huddle.github.io/Resemble.js/)を使っており、若干遅い。

本家ドキュメントにもCSSの要素の一部を指定して使うこと推奨と書かれているし、そもそもJSや美しいDiffにこだわらなければもっと高速な解がありそうな感じがした。


## 似たライブラリ

これを調べている間に、BBC-NEWSが作っているwraith (https://github.com/BBC-News/wraith) というものも見つけた。

こちらは既存の2つのサイト(英語版とロシア版など)の違いをフルページで比較するために作られたようなライブラリ。
サイト2つ+比較するページを指定して置くとdiffをとってくれる。やたらと遅いが、まぁ放置しておけばいいでしょという考えみたい。