フロントエンドエンジニアのUIデバッグ

## プロローグ
突然ですが、皆さん、間違い探しは得意ですか？
![427852.png](https://qiita-image-store.s3.amazonaws.com/0/192967/c534b7ec-1c8f-e5f6-9e82-96bc1ecadb30.png)
フロントエンドエンジニアのほとんどの方は、いわゆるマークアップ(html,css)部分の<font color="red">質</font>に関して、指摘を受け、頭を悩ました経験があるのではないでしょうか？  
その理由の１つとして、html,cssにはエラーがなく、表示してみて、デザインデータとブラウザ間で間違い探しをしなければならない点が挙げられます。そこで、自動でスクショを取るなどを行うUIテストの何かを、デバッグとして利用することでマークアップの質を改善する方法がないか検討・挑戦してみました。

## そもそもUIテストとは
探して見たところ、明確な定義は見つからなかったので、[まとめていただいているページ](https://qiita.com/yutaChaos/items/857472c7d3c65d3cf316)から引用します。

>### UIテスト
>seleniumやappinumなどの実際のブラウザやアプリを動かすソフトウェアを使って行うテスト、一番粒度が大きい。

>#### メリット
>- 全てを連結してテストをすることができるため、確認できる範囲は大きく要件まで確認できる
>- ほぼ実際に動く環境に確認できるためブラウザ環境依存などの外部要因も確認できる

>#### デメリット
>- 確認範囲が大きいため、複雑なコードなることが大きくメンテナンスが大変になりがち
>- ブラックボックステストで行われるため、バグの発生箇所がわかりづらい

ブラウザベースの全ての機能や表示をテストするようで、そのテスト方法の中で、画面のキャプチャを撮るという方法を採用されることが多いらしいです。

jsでSSRまでしてます！という場合は、全般のUIテストは可能の様子です。
フロントエンドがテンプレートを作成し、開発側がテキストやURLなどの実際のデータを流しこむフローの場合、フロントエンドとしては結局、キャプチャを撮るところまでの記載が多いので、キャプチャを目検しているように思えます...

## step1
目検以外の方法で、表示の違いを表示する

### 解決方法
`画像差分を利用する`
具体的には、[imageMagick](https://www.imagemagick.org/script/index.php)のcompare機能を使用すれば解決できました。
画像さえ用意してしまえば、画像差分を表示してくれます。

```shell
compare -metric AE {比較画像1path}/test1.png {比較画像2path}/test2.png {出力先path}/diff.png
```

<img width="220" src="https://qiita-image-store.s3.amazonaws.com/0/192967/80e1f2d3-7cd0-cda5-742d-fe434b78b344.png"> <img width="220" src="https://qiita-image-store.s3.amazonaws.com/0/192967/94808c69-99d9-1668-e46f-042eff74d775.png"> <img width="220" src="https://qiita-image-store.s3.amazonaws.com/0/192967/6abd2983-3aa1-62dc-e3e6-c69aeb25f5e5.png">



左：　デザインデータ, 真ん中：　編集中画面, 右：　差分
差分は赤で出力されます。

## step2
できるだけ手間なく作業中の画面のスクショを用意する
`cmd + shift + 4`で範囲選択して用意するわけにもいかないです。

### 解決方法
`ブラウザの機能に頼る`
[コマンドを少し打つだけでスクショが撮れる](https://requlog.com/self-branding/blog/chrome-full-screen-capture/)ので、これを活用してみます。
devv-toolで`cmd + shift + p` として `capture`と入力します。

fullsizeはページ全体, capture screenshotは現在表示されている範囲のキャプチャがダウンロードされます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/192967/58cd3556-fb20-fc42-7d30-96c798c48e57.png)

## 問題
やはり画像の管理の手間がある
長期的な運用を考えると少しでも自動化したい。

### 解決方法
[seleniumでchromeの自動操作を行う](https://qiita.com/Rasukarusan/items/0ca204d5b0f0fb876252)

1. [chrome-driverの環境セットアップを行う](https://qiita.com/Rasukarusan/items/0ca204d5b0f0fb876252)
2. `npm i -g selenium-standalone` 
3. `npm i selenium-webdriver` で[webdriverのセットアップ](https://qiita.com/sato1043/items/0ebc8198e5cb0685cf7f)
4. `selenium-standalone start` でseleniumserverを起動
5. 作業しているlocalhostのportを空けておく
6. `node try.js` でスクリプトを処理させる


```javascript:try.js
var webdriver = require('selenium-webdriver');

var chromeCapabilities = webdriver.Capabilities.chrome()
var chromeOptions = {
    'args': [ 'window-size=320,700' ]
}
chromeCapabilities.set('chromeOptions', chromeOptions);
var driver = new webdriver.Builder()
    .withCapabilities(chromeCapabilities)
    .build();

driver.get('http://localhost:8000/') //スクショしたいページのurlを指定


driver.wait(function () { //立ち上がるのに時間かかるので待機
    return driver.takeScreenshot().then(
        function(image, err) {
            require('fs').writeFile('out.png', image, 'base64', function(err) {
                console.log(err);
            })
        }
    )
}, 3000)

// 画像差分の実行
require('child_process').exec('compare -metric AE {比較画像1path}/test1.png {比較画像2path}/test2.png {出力先path}/diff.png', function(err, stdout, stderr) {
    if (err) { console.log(err); }
    console.log(stdout)
})

//スクショした画像の削除
require('fs').unlink('{出力先path}/diff.png', function (err) {
    console.log(err)
})

driver.quit() //終了
```
javasciptで実装しているリファレンスがなさすぎて大変ですが、[chromeで立ち上げる際のoption設定方法](https://gist.github.com/anandsunderraman/e351485319a8a0e7df7e)などを参考にしています。
画像サイズは[imageMagickにて縮小](http://imagemagick.rulez.jp/archives/93)を行うのも良いと思います。

```shell
convert    out.png    -resize    320x    out.png
```

## まとめ
selenium, imageMagick, Node.jsを利用して、UIデバッグ作業の自動化に繋げることができました。
今後も改良を加えていきます！
1. seleniumでスクリーンショット撮影
2. imageMagickで画像の調整
3. imageMagickで画像差分の表示

### 今後の課題など
#### 画像差分
背景の高さが異なる場合大きな差分となって、ほとんど真っ赤になるので、[より分かりすい画像差分の取り方](https://qiita.com/Quramy/items/290f7a33c350d910ebab)を考えたいところ。

#### 打つコマンドが多い
seleniumによる画像生成を１コマンドで実行したいので、[concurrentlt](https://www.npmjs.com/package/concurrently), [wait-on](https://www.npmjs.com/package/wait-on)の導入を試してみたい。

### puppeteer
Nodejs環境下でのUIテストはpuppeteerが良いとのこと。
2017年ごろからのツールで新しいですが、google製なので、ぜひpuppeteerでも試したい

#### 注意点
今回、試したのはあくまでも静的なページの差分確認です。
テンプレートとして作成していて、入力されるデータが表示される度に変わるようなページの場合、少なくとも下記の内容が分かりやすい、いくつかのデザインパターンをご用意していただく必要があります。（例. ECの検索結果ページなど）

- 画像: 短辺合わせ・長辺合わせ
- テキスト: 最低文字数, 最大文字数
- 横幅: spなら375px, 320px, ランドスケープ、 pcならpad系も
- 余白: 可変, 固定