WEBアプリケーション検証でビジュアルリグレッションテストの導入を検討しています。
cypress と reg-cli を利用して before/after スクリーンショット比較環境をトライしたときの備忘録です。
導入し易く本格的に活用していきたいと思います。
目次
やること
- システム改修前後のスクリーンショットを cypress で before/after に保存する
- reg-cli で before/after 内画像を比較し差分を確認する
cypress環境構築
nodejs,npm インストールは、環境に合わせて実施ください
cypress のインストール
mkdir -p /myproduct
cd /myproduct
npm init -y
npm install cypress --save-dev
cypress 実行コマンドを package.json に追加
"scripts": {
"cypress:open": "cypress open",
"cypress:run": "cypress run"
},
Cypress Test Runner を実行
npm run cypress:open
Cypress 構成
cypress test runner を実行すると cypress ディレクトリが生成されます。
cypress
|- fixtures //テストデータを置く
|- integration //spec ファイルを置く
|- plugins
|- support
|- screenshots //スクリーンショットが保存される
|- package.json
|- package-lock.json
|- cypress.json
# サンプル spec を削除
rm integration/examples
スクリーンショット取得実装
cypress 環境変数の作成
スクリーンショットサイズ・キャプチャモード、ウェイトの環境変数を cypress.json に指定する
{
"env": {
"ss_wait_msec": 1000,
"ss_view_width": 1340,
"ss_view_height": 1000,
"ss_capture": "fullPage"
}
}
スクリーンショットを取得するアクセスリスト(テストデータ)の作成
fixtures/visual-regression-test/pages.json
[
{
"test_id": "001",
"uri": "/001"
},
{
"test_id": "002",
"uri": "/002"
},
{
"test_id": "003",
"uri": "/003"
}
]
スクリーンショットを取得する spec ファイルの実装
改修前のスクリーンショット保存
integration/visual-regression-test/before.spec.js
スクリーンショット対象は、テストデータに指定
describe('before screenshot', function() {
const pages = require('../../fixtures/visual-regression-test/pages.json')
const domain = 'https://before.com'
const ss_dir = 'before'
var test_id = ''
var ss_path = ''
var url = ''
pages.forEach(({ test_id, uri }) => {
context(test_id, () => {
beforeEach(() => {
url = domain + uri
cy.visit(url)
})
it('take screenshot', function() {
ss_path = ss_dir + '/' + test_id
cy.wait(Cypress.env('ss_wait_msec'))
cy.viewport(Cypress.env('ss_view_width'), Cypress.env('ss_view_height'))
cy.screenshot(ss_path, {
capture: Cypress.env('ss_capture')
})
})
})
})
})
改修後のスクリーンショット保存
integration/visual-regression-test/after.spec.js
リクエスト先は、before と同じテストデータ pages.json を再利用
describe('after screenshot', function() {
const pages = require('../../fixtures/visual-regression-test/pages.json')
const domain = 'https://after.com'
const ss_dir = 'after'
var test_id = ''
var ss_path = ''
var url = ''
pages.forEach(({ test_id, uri }) => {
context(test_id, () => {
beforeEach(() => {
url = domain + uri
cy.visit(url)
})
it('take screenshot', function() {
ss_path = ss_dir + '/' + test_id
cy.wait(Cypress.env('ss_wait_msec'))
cy.viewport(Cypress.env('ss_view_width'), Cypress.env('ss_view_height'))
cy.screenshot(ss_path, {
capture: Cypress.env('ss_capture')
})
})
})
})
})
スクリーンショット保存先の変更
デフォルトではスクリーンショット保存先が spec.js ファイル毎に別れます
- screenshots/visual-regression-test/
before.spec.js
/before/001.png - screenshots/visual-regression-test/
after.spec.js
/after/001.png
reg-cli でbefore/after を指定しやすいパスにしたいので spec.js ファイル名をパスから除く形に plugin で対応
- screenshots/visual-regression-test/before/001.png
- screenshots/visual-regression-test/after/001.png
plugins/index.js
に追加
const path = require('path');
const fs = require('fs')
module.exports = (on, config) => {
on('after:screenshot', (details) => {
var str = details.path
var new_path = str.replace(/[a-z-]+\.spec\.js/, '')
var new_dir = path.dirname(new_path)
fs.mkdirSync(new_dir, { recursive: true })
fs.renameSync(details.path, new_path)
return { path: new_path }
})
}
例外発生時にテストが中断されないように対応
デフォルトの動作として例外発生時は、テストが中断されるようです
テストが中断されないように uncaught exceptions
イベントで対応
support/index.js
に追加
Cypress.on('uncaught:exception', (err, runnable) => {
// returning false here prevents Cypress from
// failing the test
return false
})
before/after スクリーンショットを取得する
実装した before/after.spec.js を実行します
reg-cliの追加インストール
cd ./myproduct
npm install reg-cli --save-dev
スクリーンショット画像を比較
$ reg-cli /path/to/actual-dir /path/to/expected-dir /path/to/diff-dir -R ./report.html
cd ./myproduct
./node_modules/.bin/reg-cli \
./cypress/screenshots/visual-regression-test/before \
./cypress/screenshots/visual-regression-test/after \
./cypress/screenshots/visual-regression-test/diff \
-R ./cypress/screenshots/visual-regression-test/report/index.html
比較結果が出力されます
✘ change cypress\screenshots\visual-regression-test\before\001.png
✔ pass cypress\screenshots\visual-regression-test\before\003.png
✘ change cypress\screenshots\visual-regression-test\before\002.png
✘ 2 file(s) changed.
✔ 1 file(s) passed.
スクリーンショット差分ファイル
コマンド引数で指定した diff ディレクトリに差分画像が出力される
差分があるスクリーンショットのみ出力されるようです
./cypress/screenshots/visual-regression-test/diff
スクリーンショット結果レポート
コマンド引数で指定した report ファイルに全ての比較結果が出力されます
./cypress/screenshots/visual-regression-test/report/index.html
比較された画像の結果がわかりやすくリスト表示されます
画像毎の比較結果は、複数の表示モードで確認することができます。
- Diff
- 2枚の差分を表示する
- Slide
- 画像上でマウスを左右にスライドすることで1枚目(左)、2枚目(右)を表示する
- 2up
- 左右に並べて表示する
- Blend
- 2枚を重ねて表示する
- Toggle
- toggle ボタンで画像を切り替えて表示する
比較精度を調整
-M, --matchingThreshold オプションを指定することで人の見た目に合わせた比較をすることができました(すごい!)
./node_modules/.bin/reg-cli \
./cypress/screenshots/visual-regression-test/before \
./cypress/screenshots/visual-regression-test/after \
./cypress/screenshots/visual-regression-test/diff \
-R ./cypress/screenshots/visual-regression-test/report/index.html
-M 0.2
-M 0.2
0 - 1 の範囲を指定できるようで、小数点指定してみました。
参考にさせていただいたページ
https://qiita.com/natsu_mikan/items/692018262b617bb87859
https://qiita.com/hurikake06/items/9930a9ad223e86320c8f
https://www.cypress.io/
https://github.com/reg-viz/reg-cli