tag:crieit.net,2005:https://crieit.net/tags/BackstopJS/feed 「BackstopJS」の記事 - Crieit Crieitでタグ「BackstopJS」に投稿された最近の記事 2020-12-20T00:38:39+09:00 https://crieit.net/tags/BackstopJS/feed tag:crieit.net,2005:PublicArticle/16378 2020-12-16T23:42:55+09:00 2020-12-20T00:38:39+09:00 https://crieit.net/posts/backstop-trial-and-error-20201215 BackstopJS で背景画像の高さを `vh` 単位で指定したページで画像やスクリーンショットが引き伸ばされる現象についてメモ (未解決) <p>メインビジュアル等で背景画像の高さを vh 単位で指定したページで、画像やスクリーンショットが引き伸ばされる現象に遭遇してしまいました。正常なスクリーンショットが撮影できないので困った……ということで、その現象について調べたメモです。</p> <h2 id="調査"><a href="#%E8%AA%BF%E6%9F%BB">調査</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/garris/BackstopJS/issues/785">Issues using vh units in CSS ・ Issue #785 ・ garris/BackstopJS</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/garris/BackstopJS/issues/820">Take screenshot without resizing page ・ Issue #820 ・ garris/BackstopJS</a></li> </ul> <p>調べたらそれと思しき現象の Issues が上がっていました。ただ、どちらも現在進行形でオープンになっているので解決には至っていない模様……。</p> <h2 id="検証"><a href="#%E6%A4%9C%E8%A8%BC">検証</a></h2> <p>スレッドの中で提示された対処法:</p> <ol> <li><code>"mergeImgHack": true,</code> あるいは高さ決め打ちならば <code>"mergeImgHack": 1024,</code> のような値を <code>backstop.json</code> のルートに追記する</li> <li>beta版を使用する</li> </ol> <p>1.は効果がなかったので2.を試そうと思ったのですが、 Github のブランチ (<code>2.6.7</code>)と npm で指定した場合(<code>4.3.3</code>)で Beta のバージョンが異なる模様。</p> <p><code>package.json</code> の <code>dependencies</code> や <code>devDependencies</code> に <code>"backstopjs": "https://github.com/garris/BackstopJS#beta"</code> と指定すると <code>2.6.7</code>、<code>"backstopjs": "beta",</code> と指定すると <code>4.3.3</code> が落ちてきます。</p> <p>そこで各バージョンで何度か試行錯誤を繰り返しました。</p> <ul> <li><code>5.0.7</code>: <ul> <li>最新版</li> <li>背景画像が引き伸ばされる現象が発生する</li> <li>engine で chromy を指定しようとしたところ、 <code>createBitmaps | Chromy is no longer supported in version 5+. Please use version 4.x.x for chromy support.</code> とのこと。 <code>2.6.7</code> ではそこそこそれっぽい表示になったので <code>engine</code> を切り替えることができれば……と思ったのですが、ダメそうです</li> </ul></li> <li><code>4.3.3</code>: <ul> <li>背景画像が引き伸ばされる現象の解決には至らず</li> <li>いろいろ今どきに近くなっているので各種設定はしやすい</li> </ul></li> <li><code>2.6.7</code>: <ul> <li>昨日別の場所で試したときは動いたのですが動作再現できず</li> <li>内部的に PhantomJS を使用している模様。2018年に開発終了しているので今更使いたくはない</li> <li>設定を node script から渡すとき、オブジェクトではなくファイルパスを渡す模様。とすると、いったん <code>backstop.json</code> を書き出す処理を挟まないといけない</li> </ul></li> </ul> <p>よくよく先程のスレッドを見直してみると <code>npm install backstopjs@beta</code> とか <code>4.3.3</code> と言ったワードがあるので普通に npm 指定の方で良さそうですね。</p> <p>ひとまず <code>devDependencies</code> に <code>"backstopjs": "beta"</code> を指定してまた色々試してみたいと思います。</p> <h2 id="備考"><a href="#%E5%82%99%E8%80%83">備考</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://swet.dena.com/entry/2018/04/26/152326">Puppeteerによるフルページスクリーンショットを画像遅延読み込みに対応させる - DeNA Testing Blog</a></li> </ul> <p>スクロールに応じてコンテンツが表示される系のアニメーションもあるので、「下端までスクロールしてからスクリーンショットを撮影する」も対応したいですね……。</p> <h2 id="追記(2020/12/20)"><a href="#%E8%BF%BD%E8%A8%98%282020%2F12%2F20%29">追記(2020/12/20)</a></h2> <p>色々試行錯誤した結果のリポジトリを晒しておきます。</p> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/arm-band/test_backstop_randa_back_stopper_2">arm-band/test_backstop_randa_back_stopper_2: BackstopJS のテストです。</a></li> </ul> <p>これは本当、どうしたものか……。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/garris/BackstopJS/issues/785">Issues using vh units in CSS ・ Issue #785 ・ garris/BackstopJS</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/garris/BackstopJS/issues/820">Take screenshot without resizing page ・ Issue #820 ・ garris/BackstopJS</a></li> </ul> <h3 id="スクリプト"><a href="#%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88">スクリプト</a></h3> <h4 id="複数枚のスクリーンショットを繋ぎ合わせる"><a href="#%E8%A4%87%E6%95%B0%E6%9E%9A%E3%81%AE%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%E3%82%92%E7%B9%8B%E3%81%8E%E5%90%88%E3%82%8F%E3%81%9B%E3%82%8B">複数枚のスクリーンショットを繋ぎ合わせる</a></h4> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/garris/BackstopJS/issues/820#issuecomment-404963122">Take screenshot without resizing page ・ Issue #820 ・ garris/BackstopJS</a></li> </ul> <h4 id="下端までスクロールさせる"><a href="#%E4%B8%8B%E7%AB%AF%E3%81%BE%E3%81%A7%E3%82%B9%E3%82%AF%E3%83%AD%E3%83%BC%E3%83%AB%E3%81%95%E3%81%9B%E3%82%8B">下端までスクロールさせる</a></h4> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://swet.dena.com/entry/2018/04/26/152326">Puppeteerによるフルページスクリーンショットを画像遅延読み込みに対応させる - DeNA Testing Blog</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://gist.github.com/nnks1010/10abf3032933609d1b2bd5b99fc12586">絶対顔本スクレイピングするマン</a></li> </ul> <h4 id="Node.js での実行中スクリプトの絶対パス"><a href="#Node.js+%E3%81%A7%E3%81%AE%E5%AE%9F%E8%A1%8C%E4%B8%AD%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%81%AE%E7%B5%B6%E5%AF%BE%E3%83%91%E3%82%B9">Node.js での実行中スクリプトの絶対パス</a></h4> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://gist.github.com/uupaa/da42698d6b2d2cbb3cca">node.js で絶対パスや相対パスを取得する方法 npm __dirname</a></li> </ul> arm-band tag:crieit.net,2005:PublicArticle/16231 2020-11-22T14:26:24+09:00 2020-11-24T23:41:16+09:00 https://crieit.net/posts/backstopjs-test-20201122 BackstopJS を試す (Error: Failed to launch the browser process! エラー発生→ puppeteer のバージョンを指定して解決) <h2 id="経緯"><a href="#%E7%B5%8C%E7%B7%AF">経緯</a></h2> <p><a href="https://crieit.net/posts/jest-test">Jest でユニットテストができる</a>ことは分かりました。何かを処理するものに関しては行けそうな気がします。</p> <p>……しかし、Webサイトの場合は見た目も気になります。見た目をテストするにはどううれば良いのか……と考えていたところ、 BackstopJS というものがあることを知ったので試してみることにします。</p> <h2 id="準備"><a href="#%E6%BA%96%E5%82%99">準備</a></h2> <p>見た目のテストのためには何かページを生成するものが必要です。</p> <p>今回は簡単に試せる環境として、手前味噌ですが <a target="_blank" rel="nofollow noopener" href="https://github.com/arm-band/mori">arm-band/mori</a> を使うことにしました。</p> <h3 id="1. パッケージ追加"><a href="#1.+%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E8%BF%BD%E5%8A%A0">1. パッケージ追加</a></h3> <p><code>package.json</code> に <code>backstopjs</code> を追加します。</p> <p>```json:package.json<br /> // 略<br /> "devDependencies": {<br /> "backstopjs": "^5.0.6", // 追加<br /> "browser-sync": "^2.26.12",<br /> // 略<br /> },<br /> // 略</p> <pre><code><br />### 2. yarn これで `yarn` してインストールを待ちます。 ```bash > yarn </code></pre> <h3 id="BackstopJS の準備"><a href="#BackstopJS+%E3%81%AE%E6%BA%96%E5%82%99">BackstopJS の準備</a></h3> <p>後は手順通りに <code>backstop init</code> して</p> <pre><code class="bash">> backstop init </code></pre> <p>生成された <code>backstop.json</code> の <code>scenarios</code> -> <code>url</code> を編集。今回は Browsersync のローカルサーバにしたいので <code>https://localhost:3000/</code> で。</p> <p>```json:package.json<br /> // 略<br /> "scenarios": [<br /> {<br /> "label": "BackstopJS Homepage",<br /> "cookiePath": "backstop_data/engine_scripts/cookies.json",<br /> // "url": "https://garris.github.io/BackstopJS/",<br /> "url": "https://localhost:3000/", // 変更<br /> "referenceUrl": "",<br /> // 略<br /> }<br /> ]<br /> // 略</p> <pre><code><br />## 検証1 (失敗) ここまで準備をしたら、正解の見本を保存するために `backstop reference` でスクリーンショットを撮ります。 まずは `yarn start` で Gulpタスク を走らせて `https://localhost:3000/` を上げます。 次に、上述の `backstop reference` コマンドを実行します。 ```bash > backstop reference BackstopJS v5.0.6 Loading config: PATH\TO\TEST_PROJECT\randa_back_stopper\backstop.json COMMAND | Executing core for "reference" clean | backstop_data/bitmaps_reference was cleaned. createBitmaps | Selected 1 of 1 scenarios. COMMAND | Command "reference" ended with an error after [1.414s] Error: Failed to launch the browser process! TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/master/docs/troubleshooting.md at onClose (PATH\TO\TEST_PROJECT\randa_back_stopper\node_modules\puppeteer\lib\Launcher.js:750:14) at ChildProcess.<anonymous> (PATH\TO\TEST_PROJECT\randa_back_stopper\node_modules\puppeteer\lib\Launcher.js:740:61) at ChildProcess.emit (events.js:326:22) at Process.ChildProcess._handle.onexit (internal/child_process.js:276:12) # 略 </code></pre> <p>……あれ?失敗しました。</p> <blockquote> <p>Command "reference" ended with an error after</p> <p>Error: Failed to launch the browser process!</p> </blockquote> <p>エラーメッセージ的にはこの部分が原因っぽいですね。</p> <p>そして、問題を起こしているのは <code>puppeteer</code> のようです。</p> <p>ちなみに、 BackstopJS がスクリーンショットを撮る際は Puppeteer からヘッドレスブラウザとして Chromium でレンダリングしている模様。</p> <p>ということで、原因は Puppeteer にあり。エラー文で検索しましたが、イマイチ情報が少ない上にあまり新しい情報がないので、半ば手探りで追及してみることになりました……。</p> <h2 id="Puppeteer の検証1"><a href="#Puppeteer+%E3%81%AE%E6%A4%9C%E8%A8%BC1">Puppeteer の検証1</a></h2> <p>まずはそもそも Puppeteer が自分の環境で動くか確認してみます。</p> <pre><code class="bash">> node -v v14.8.0 > npm -v 6.14.7 </code></pre> <p>Node.js とnpm のバージョン確認。</p> <p>この状態で新規のプロジェクトを作成します。</p> <h3 id="package.json"><a href="#package.json">package.json</a></h3> <p>```json:package.json<br /> {<br /> "name": "puppeteer_test",<br /> "version": "1.0.0",<br /> "description": "",<br /> "main": "index.js",<br /> "scripts": {<br /> "test": "echo \"Error: no test specified\" && exit 1"<br /> },<br /> "author": "",<br /> "license": "ISC",<br /> "devDependencies": {<br /> "puppeteer": "^5.5.0"<br /> }<br /> }</p> <pre><code><br />`npm init` で `package.json` を用意して、 `yarn add --dev puppeteer` で `devDependencies` に追加します。 ### index.js ```javascript:index.js const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://google.com/'); await page.screenshot({path: 'screenshot.png'}); await browser.close(); })(); </code></pre> <p>Google のスクリーンショットを撮影するだけの簡単な JS を用意します。</p> <p>これで</p> <pre><code class="bash">> yarn # 略 > node index.js > </code></pre> <p>……普通に撮影でき、 <code>screenshot.png</code> が保存されました。問題ありません。</p> <h2 id="Puppeteer の検証2"><a href="#Puppeteer+%E3%81%AE%E6%A4%9C%E8%A8%BC2">Puppeteer の検証2</a></h2> <p>次に、 BackstopJS の内部で使用されている Puppeteer のバージョンを確認するために <code>node_modules/backstopjs/package.json</code> を調べます。</p> <p>```json:package.json<br /> {<br /> "name": "backstopjs",<br /> "version": "5.0.6",<br /> "description": "BackstopJS: Catch CSS curveballs.",<br /> "bin": {<br /> "backstop": "./cli/index.js"<br /> },<br /> "scripts": {<br /> "lint": "eslint 'compare/<em>.js' 'compare/src/<strong>/*.js' 'core/</strong>/</em>.js' 'cli/<strong>/*.js' 'capture/</strong>/<em>.js' 'test/<strong>/*.js'",<br /> "format": "prettier-eslint --write \"compare/src/</strong>/</em>.js\"",<br /> "genConfig": "node ./cli/index.js genConfig",<br /> "init": "node ./cli/index.js init",<br /> "reference": "node ./cli/index.js reference",<br /> "test": "node ./cli/index.js test",<br /> "approve": "node ./cli/index.js approve",<br /> "openReport": "node ./cli/index.js openReport",<br /> "report": "node ./cli/index.js openReport",<br /> "echo": "node ./cli/index.js echo",<br /> "unit-test": "mocha --reporter spec --recursive 'test/<strong>/*_spec.js'",<br /> "precommit": "lint-staged",<br /> "build-compare": "cp ./node_modules/diverged/src/diverged.js ./compare/output/ && cp ./node_modules/diff/dist/diff.js ./compare/output/ && webpack --config ./compare/webpack.config.js && npm run lint",<br /> "dev-compare": "webpack-dev-server --content-base ./compare/output --config ./compare/webpack.config.js",<br /> "integration-test": "rm -rf newdir && mkdir newdir && cd newdir && node ../cli/index.js genConfig && node ../cli/index.js reference && node ../cli/index.js test && node -e \"require('../')('test')\"",<br /> "smoke-test": "cd test/configs/ && node ../../cli/index.js test --config=backstop_features",<br /> "smoke-test-docker": "cd test/configs/ && node ../../cli/index.js test --config=backstop_features --docker",<br /> "sanity-test": "cd test/configs/ && node ../../cli/index.js test",<br /> "sanity-test-docker": "cd test/configs/ && node ../../cli/index.js test --docker",<br /> "kill-zombies": "pkill -f \"(chrome)?(--headless)\"",<br /> "copy-report-bundle": "mkdir -p test/configs/backstop_data/html_report && cp compare/output/index_bundle.js test/configs/backstop_data/html_report/",<br /> "build-and-copy-report-bundle": "npm run build-compare && npm run copy-report-bundle",<br /> "remote": "node ./cli/index.js remote",<br /> "stop": "curl http://localhost:3000/stop"<br /> },<br /> "lint-staged": {<br /> "compare/src/</strong>/*.js": [<br /> "node_modules/.bin/prettier --single-quote --write",<br /> "git add"<br /> ]<br /> },<br /> "repository": {<br /> "type": "git",<br /> "url": "https://github.com/garris/backstopjs.git"<br /> },<br /> "author": "https://github.com/garris/BackstopJS/graphs/contributors",<br /> "license": "MIT",<br /> "main": "core/runner.js",<br /> "devDependencies": {<br /> "assert": "^1.4.1",<br /> "babel-core": "^6.26.3",<br /> "babel-loader": "^7.1.5",<br /> "babel-preset-es2015": "^6.24.1",<br /> "babel-preset-react": "^6.24.1",<br /> "backstop-twentytwenty": "^1.0.4",<br /> "eslint": "^5.6.1",<br /> "eslint-config-semistandard": "^12.0.1",<br /> "eslint-config-standard": "^12.0.0",<br /> "eslint-plugin-import": "^2.14.0",<br /> "eslint-plugin-node": "^7.0.1",<br /> "eslint-plugin-promise": "^4.0.1",<br /> "eslint-plugin-react": "^7.11.1",<br /> "eslint-plugin-standard": "^4.0.0",<br /> "file-loader": "^2.0.0",<br /> "lint-staged": "^4.3.0",<br /> "mocha": "^5.2.0",<br /> "mockery": "^1.4.0",<br /> "prettier": "^1.14.3",<br /> "prettier-eslint-cli": "^4.7.1",<br /> "react": "^15.6.1",<br /> "react-dom": "^15.6.1",<br /> "react-modal": "^3.0.3",<br /> "react-redux": "^5.0.6",<br /> "react-sticky": "^6.0.1",<br /> "react-toggle-button": "^2.1.0",<br /> "react-visibility-sensor": "^3.11.1",<br /> "redux": "^3.7.2",<br /> "sinon": "^1.17.7",<br /> "styled-components": "^2.1.2",<br /> "url-loader": "^1.1.1",<br /> "webpack": "^4.43.0",<br /> "webpack-cli": "^3.1.2",<br /> "webpack-dev-server": "^3.3.1"<br /> },<br /> "dependencies": {<br /> "chalk": "^1.1.3",<br /> "diverged": "^0.1.3",<br /> "fs-extra": "^0.30.0",<br /> "jump.js": "^1.0.2",<br /> "junit-report-builder": "^1.3.3",<br /> "lodash": "^4.17.11",<br /> "merge-img": "^2.1.3",<br /> "minimist": "^1.2.0",<br /> "node-resemble-js": "^0.2.0",<br /> "object-hash": "1.1.5",<br /> "opn": "^5.3.0",<br /> "os": "^0.1.1",<br /> "p-map": "^1.1.1",<br /> "path": "^0.12.7",<br /> "portfinder": "^1.0.17",<br /> "puppeteer": "^2.0.0",<br /> "resolve": "^1.11.1",<br /> "super-simple-web-server": "^1.1.2",<br /> "temp": "^0.8.3"<br /> }<br /> }</p> <pre><code><br />`puppeteer` のバージョンは…… `2.0.0` ?!先ほど入れた最新版は `5.5.0` だったのでかなりバージョンに乖離があります。 ということで先程の Puppeteer のテストプロジェクトの `package.json` を直します。 ```json:package.json { "name": "puppeteer_test", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "devDependencies": { "puppeteer": "^2.0.0" } } </code></pre> <p>はい。 <code>2.0.0</code> です。これで <code>yarn</code> し直して <code>node index.js</code> を実行。</p> <pre><code class="bash">> node index.js (node:28172) UnhandledPromiseRejectionWarning: Error: Failed to launch the browser process! TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/master/docs/troubleshooting.md at onClose (PATH\TO\TEST_PROJECT\puppeteer_test\node_modules\puppeteer\lib\Launcher.js:750:14) at ChildProcess.<anonymous> (PATH\TO\TEST_PROJECT\puppeteer_test\node_modules\puppeteer\lib\Launcher.js:740:61) at ChildProcess.emit (events.js:326:22) at Process.ChildProcess._handle.onexit (internal/child_process.js:276:12) </code></pre> <p><code>Error: Failed to launch the browser process!</code> のエラーが出て、 BackstopJS のプロジェクトで出た内容を再現できました。</p> <p>エラーの発生個所も <code>node_modules\puppeteer\lib\Launcher.js:750:14</code> 以下同じです。</p> <h3 id="念のための確認"><a href="#%E5%BF%B5%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE%E7%A2%BA%E8%AA%8D">念のための確認</a></h3> <p>エラー文の中にあるトラブルシューティングなど、いくつかの記事で「 <code>puppeteer.launch()</code> のオプションで <code>ignoreDefaultArgs: ['--disable-extensions']</code> を指定すると良い」と書かれていたので、一応やってみます。</p> <p>```javascript:index.js<br /> const puppeteer = require('puppeteer');</p> <p>(async () => {<br /> //const browser = await puppeteer.launch();<br /> const browser = await puppeteer.launch({<br /> ignoreDefaultArgs: ['--disable-extensions'],<br /> });</p> <p>const page = await browser.newPage();<br /> await page.goto('https://google.com/');<br /> await page.screenshot({path: 'screenshot.png'});</p> <p>await browser.close();<br /> })();</p> <pre><code><br />修正して、実行。 ```bash > node index.js (node:31444) UnhandledPromiseRejectionWarning: Error: Failed to launch the browser process! TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/master/docs/troubleshooting.md at onClose (PATH\TO\TEST_PROJECT\puppeteer_test\node_modules\puppeteer\lib\Launcher.js:750:14) at ChildProcess.<anonymous> (PATH\TO\TEST_PROJECT\puppeteer_test\node_modules\puppeteer\lib\Launcher.js:740:61) at ChildProcess.emit (events.js:326:22) at Process.ChildProcess._handle.onexit (internal/child_process.js:276:12) </code></pre> <p>はい、変わりませんでした。</p> <h2 id="検証2 (成功)"><a href="#%E6%A4%9C%E8%A8%BC2+%28%E6%88%90%E5%8A%9F%29">検証2 (成功)</a></h2> <p>以上より、 Puppeteer のバージョンをどうにかすれば BackstopJS が動きそうなことが分かりました。</p> <p>そこで、 Yarn の依存関係の解決オプションの <code>resolutions</code> を試してみることにします。</p> <p>```json:package.json<br /> // 略<br /> "devDependencies": {<br /> "backstopjs": "^5.0.6", // 追加<br /> "browser-sync": "^2.26.12",<br /> // 略<br /> },<br /> "resolutions": {<br /> "puppeteer": "^5.5.0" // 追加<br /> },<br /> // 略</p> <pre><code><br />これで `yarn` し直して、念のため `backstop_data`ディレクトリ と `backstop.json` を削除して `backstop init` をやり直し、再度 `url` を `https://localhost:3000/` に直した上で、 `backstop reference` を実行。 ```bash > backstop reference BackstopJS v5.0.6 Loading config: PATH\TO\TEST_PROJECT\randa_back_stopper\backstop.json COMMAND | Executing core for "reference" clean | backstop_data/bitmaps_reference was cleaned. createBitmaps | Selected 1 of 1 scenarios. CREATING NEW REFERENCE FILE CREATING NEW REFERENCE FILE Cookie state restored with: [ { "path": "/", "name": "yourCookieName", "value": "yourCookieValue", "expirationDate": 1798790400, "hostOnly": false, "httpOnly": false, "secure": false, "session": false, "sameSite": "no_restriction", "url": "https://.www.yourdomain.com" } ] Cookie state restored with: [ { "path": "/", "name": "yourCookieName", "value": "yourCookieValue", "expirationDate": 1798790400, "hostOnly": false, "httpOnly": false, "secure": false, "session": false, "sameSite": "no_restriction", "url": "https://.www.yourdomain.com" } ] Browser Console Log 0: JSHandle:BackstopTools have been installed. SCENARIO > BackstopJS Homepage x Close Browser Browser Console Log 0: JSHandle:BackstopTools have been installed. SCENARIO > BackstopJS Homepage x Close Browser Run `$ backstop test` to generate diff report. COMMAND | Command "reference" successfully executed in [3.752s] </code></pre> <p>動きました!</p> <h2 id="リグレッションテストの検証"><a href="#%E3%83%AA%E3%82%B0%E3%83%AC%E3%83%83%E3%82%B7%E3%83%A7%E3%83%B3%E3%83%86%E3%82%B9%E3%83%88%E3%81%AE%E6%A4%9C%E8%A8%BC">リグレッションテストの検証</a></h2> <p>ようやく <code>backstop reference</code> が動いたので、リグレッションテストを試してみます。</p> <p>まずは編集前( <code>backstop reference</code> したとき)のページのキャプチャ画像。</p> <p><a href="https://crieit.now.sh/upload_images/797102acdac6535e2fa0f80aa6f879c45fb9f477bff8c.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/797102acdac6535e2fa0f80aa6f879c45fb9f477bff8c.jpg?mw=700" alt="編集前のページのキャプチャ画像" /></a></p> <p>次に、 Scss や JS などいくつかパラメータやコードを編集して、 <code>backstop test</code> します。</p> <p><a href="https://crieit.now.sh/upload_images/2f667a2a2f4ab38ffa034b580c28939f5fb9f483a0b75.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/2f667a2a2f4ab38ffa034b580c28939f5fb9f483a0b75.jpg?mw=700" alt="編集後のページのキャプチャ画像" /></a></p> <pre><code class="bash">> backstop test BackstopJS v5.0.6 Loading config: PATH\TO\TEST_PROJECT\randa_back_stopper\backstop.json COMMAND | Executing core for "test" createBitmaps | Selected 1 of 1 scenarios. Cookie state restored with: [ { "path": "/", "name": "yourCookieName", "value": "yourCookieValue", "expirationDate": 1798790400, "hostOnly": false, "httpOnly": false, "secure": false, "session": false, "sameSite": "no_restriction", "url": "https://.www.yourdomain.com" } ] Cookie state restored with: [ { "path": "/", "name": "yourCookieName", "value": "yourCookieValue", "expirationDate": 1798790400, "hostOnly": false, "httpOnly": false, "secure": false, "session": false, "sameSite": "no_restriction", "url": "https://.www.yourdomain.com" } ] Browser Console Log 0: JSHandle:Invisible Full-moon! Browser Console Log 0: JSHandle:BackstopTools have been installed. SCENARIO > BackstopJS Homepage x Close Browser Browser Console Log 0: JSHandle:Invisible Full-moon! Browser Console Log 0: JSHandle:BackstopTools have been installed. SCENARIO > BackstopJS Homepage x Close Browser COMMAND | Executing core for "report" See: PATH\TO\TEST_PROJECT\randa_back_stopper\backstop_data\bitmaps_test\yyyymmdd-hhiiss\failed_diff_backstop_default_BackstopJS_Homepage_0_document_0_phone.png compare | ERROR { requireSameDimensions: true, size: isDifferent, content: 2.06%, threshold: 0.1% }: BackstopJS Homepage backstop_default_BackstopJS_Homepage_0_document_0_phone.png See: PATH\TO\TEST_PROJECT\randa_back_stopper\backstop_data\bitmaps_test\yyyymmdd-hhiiss\failed_diff_backstop_default_BackstopJS_Homepage_0_document_1_tablet.png compare | ERROR { requireSameDimensions: true, size: isDifferent, content: 0.70%, threshold: 0.1% }: BackstopJS Homepage backstop_default_BackstopJS_Homepage_0_document_1_tablet.png report | Test completed... report | 0 Passed report | 2 Failed report | Writing browser report report | Resources copied report | Copied json report to: PATH\TO\TEST_PROJECT\randa_back_stopper\backstop_data\bitmaps_test\yyyymmdd-hhiiss\report.json report | Copied jsonp report to: PATH\TO\TEST_PROJECT\randa_back_stopper\backstop_data\html_report\config.js COMMAND | Executing core for "openReport" openReport | Attempting to ping openReport | Remote not found. Opening backstop_data\html_report\index.html report | *** Mismatch errors found *** COMMAND | Command "report" ended with an error after [1.539s] COMMAND | Error: Mismatch errors found. at PATH\TO\TEST_PROJECT\randa_back_stopper\node_modules\backstopjs\core\command\report.js:189:17 at processTicksAndRejections (internal/process/task_queues.js:93:5) COMMAND | Command "test" ended with an error after [5.431s] COMMAND | Error: Mismatch errors found. at PATH\TO\TEST_PROJECT\randa_back_stopper\node_modules\backstopjs\core\command\report.js:189:17 at processTicksAndRejections (internal/process/task_queues.js:93:5) </code></pre> <p>エラーが出ましたね。</p> <p><a href="https://crieit.now.sh/upload_images/0e399959965269b149042714bca4d5fc5fb9f48f9e0da.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/0e399959965269b149042714bca4d5fc5fb9f48f9e0da.jpg?mw=700" alt="BackstopJS のテスト失敗画面" /></a></p> <p>また、自動的にブラウザも上がってきて上のように差分も表示されます。</p> <p><a href="https://crieit.now.sh/upload_images/0bdc13e617b71a77e0d4910f451157e85fb9f49ad8116.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/0bdc13e617b71a77e0d4910f451157e85fb9f49ad8116.jpg?mw=700" alt="BackstopJS のテスト失敗、差分の比較画面" /></a></p> <p>「DIFF」の画像をクリックした先では <code>backstop reference</code> で撮影したスクリーンショットと <code>backstop test</code> で撮影したスクリーンショットの差分をワイパーのように比較することができます。</p> <p>細かく比較できて良いですね。</p> <hr /> <p>今度は修正を元に戻して再度 <code>backstop test</code> 。</p> <pre><code class="bash">> backstop test BackstopJS v5.0.6 Loading config: PATH\TO\TEST_PROJECT\randa_back_stopper\backstop.json COMMAND | Executing core for "test" createBitmaps | Selected 1 of 1 scenarios. Cookie state restored with: [ { "path": "/", "name": "yourCookieName", "value": "yourCookieValue", "expirationDate": 1798790400, "hostOnly": false, "httpOnly": false, "secure": false, "session": false, "sameSite": "no_restriction", "url": "https://.www.yourdomain.com" } ] Cookie state restored with: [ { "path": "/", "name": "yourCookieName", "value": "yourCookieValue", "expirationDate": 1798790400, "hostOnly": false, "httpOnly": false, "secure": false, "session": false, "sameSite": "no_restriction", "url": "https://.www.yourdomain.com" } ] Browser Console Log 0: JSHandle:BackstopTools have been installed. SCENARIO > BackstopJS Homepage Browser Console Log 0: JSHandle:BackstopTools have been installed. SCENARIO > BackstopJS Homepage x Close Browser x Close Browser COMMAND | Executing core for "report" compare | OK: BackstopJS Homepage backstop_default_BackstopJS_Homepage_0_document_0_phone.png compare | OK: BackstopJS Homepage backstop_default_BackstopJS_Homepage_0_document_1_tablet.png report | Test completed... report | 2 Passed report | 0 Failed report | Writing browser report report | Resources copied report | Copied json report to: PATH\TO\TEST_PROJECT\randa_back_stopper\backstop_data\bitmaps_test\yyyymmdd-hhiiss\report.json report | Copied jsonp report to: PATH\TO\TEST_PROJECT\randa_back_stopper\backstop_data\html_report\config.js COMMAND | Executing core for "openReport" openReport | Attempting to ping openReport | Remote not found. Opening backstop_data\html_report\index.html COMMAND | Command "report" successfully executed in [0.698s] COMMAND | Command "test" successfully executed in [4.135s] </code></pre> <p>成功です。</p> <p><a href="https://crieit.now.sh/upload_images/9d46e4e325e292914e556ff4e1af90185fb9f4a71aaae.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/9d46e4e325e292914e556ff4e1af90185fb9f4a71aaae.jpg?mw=700" alt="BackstopJS のテスト成功画面" /></a></p> <p>今度はテスト成功の画面で、同じスクリーンショットが撮影できていることが確認できます。</p> <hr /> <p>ということで、軽くですが BackstopJS が使えることを確認しました。</p> <p>実際にはシナリオの編集とか色々あるようですが、ひとまず動作確認が取れたということで。</p> <h2 id="追加検証"><a href="#%E8%BF%BD%E5%8A%A0%E6%A4%9C%E8%A8%BC">追加検証</a></h2> <p>動作確認が取れたところで、より実践的になりそうな部分を深堀り。</p> <ul> <li>ブラウザサイズ: PCサイズも追加</li> <li>BrowserSync のリロード通知を削除: スクリーンショットのタイミングである/なしで分かれてしまうので一律非表示にしてDIFF検知されないようにする</li> <li>複数ページの場合: <ul> <li>シナリオを追加</li> <li><code>label</code> をファイル名に使用するので半角英数字で記述、ページごとにユニークな名前にする</li> </ul></li> <li>縦長ページの場合: 普通に全体のスクリーンショットを撮影する</li> <li><code>position: fixed;</code> のナビゲーションバー: 上端</li> </ul> <p>何回かテストを試して気になったのはこの辺りですかね。いずれもクリア、問題なさそうです。</p> <p><a href="https://crieit.now.sh/upload_images/46cfd57cc33260d9ad765b4fb3f52a9f5fb9f63e6adde.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/46cfd57cc33260d9ad765b4fb3f52a9f5fb9f63e6adde.jpg?mw=700" alt="BackstopJS のテスト失敗画面 (複数ページテスト実行、Browsersyncの通知非表示、縦長ページ、position:fixed:top;のナビゲーションバーあり)" /></a></p> <p>わざと失敗させた場合の画面。</p> <p><a href="https://crieit.now.sh/upload_images/fb85a65764f81c62dec0826822bf75475fb9f648b33ed.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/fb85a65764f81c62dec0826822bf75475fb9f648b33ed.jpg?mw=700" alt="BackstopJS の比較画面" /></a></p> <p>縦長ページでは普通に下までスクロールできます。</p> <p><a href="https://crieit.now.sh/upload_images/3ad635b6479aca9147c83bcc98a875a85fb9f653e60f6.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/3ad635b6479aca9147c83bcc98a875a85fb9f653e60f6.jpg?mw=700" alt="BackstopJS のテスト成功画面 (複数ページテスト実行、Browsersyncの通知非表示、縦長ページ、position:fixed:top;のナビゲーションバーあり)" /></a></p> <p>成功画面。最初のテストのときと同様、特に問題はなさそうです。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <h3 id="BackstopJS"><a href="#BackstopJS">BackstopJS</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://www.npmjs.com/package/backstopjs#installation">backstopjs - npm</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/garris/BackstopJS">garris/BackstopJS: Catch CSS curve balls.</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/aharenchi/items/995309c36f2449de262c">BackstopJSでビジュアルリグレッションテスト! - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/fortkle/items/00afc73508aabb7d0aca">BackstopJSで始めるリグレッションテスト - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://upinetree.hatenablog.com/entry/2018/05/13/231951">BackstopJS を利用した Visual Regression Testing の感想と工夫ポイント - upinetree's memo</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/yuzuru_xa/items/4f257d5d3f9fb598d6bb">Backstop.jsでクリスマスを少し幸せにするリファクタリング - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://blog.gaji.jp/2020/01/10/2135/">BackstopJSで行うビジュアルリグレッションテスト ++ Gaji-Laboブログ</a></li> </ul> <h3 id="Puppeteer の Error: Failed to launch the browser process! エラー対処"><a href="#Puppeteer+%E3%81%AE+Error%3A+Failed+to+launch+the+browser+process%21+%E3%82%A8%E3%83%A9%E3%83%BC%E5%AF%BE%E5%87%A6">Puppeteer の Error: Failed to launch the browser process! エラー対処</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#chrome-is-downloaded-but-fails-to-launch-on-nodejs-14">puppeteer/troubleshooting.md at main · puppeteer/puppeteer</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://officeforest.org/wp/2020/02/14/node-js%E3%81%A8puppeteer%E3%81%A7chrome%E3%82%92%E8%87%AA%E5%8B%95%E6%93%8D%E7%B8%A6%E3%81%99%E3%82%8B/">Node.jsとPuppeteerでChromeを自動操縦する | 🌴 officeの杜 🥥</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/puppeteer/puppeteer/issues/5992">Error: Failed to launch the browser process! spawn /app/node_modules/puppeteer/.local-chromium/linux-756035/chrome-linux/chrome ENOENT · Issue #5992 · puppeteer/puppeteer</a></li> </ul> <h3 id="Yarn の reasolutions"><a href="#Yarn+%E3%81%AE+reasolutions">Yarn の reasolutions</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://nju33.com/yarn/resolutions%20%E3%81%A7%E4%BE%9D%E5%AD%98%E3%81%AE%E4%BE%9D%E5%AD%98%E3%81%AE%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%82%92%E6%8C%87%E5%AE%9A%E3%81%99%E3%82%8B">yarn: resolutions で依存の依存のバージョンを指定する - nju33</a></li> </ul> arm-band