前書き
社内でnightwatchをWinMergeを使用してデグレチェックしたよーって話があったので、
WinMergeの部分も自動化してみました。
ツールを作ったのなら、こっちにも展開してくれよーと思うのだがなー。。。
やること
- nightwatchでサイトのスクリーンショットを撮影(master/作業ブランチそれぞれで)
- 撮影したスクリーンショットの差異をresemblejs出力する
事前準備
Seleniumを使用するのでJDKのインストール
公式からインストールしてください
https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
# バージョンがでればOK
$ java -version
必要なモジュールのインストール
$ npm init -y
$ npm install nightwatch
$ npm install webdriver-manager
$ npm install resemblejs
# babelも使用したので以下も入れておく
$ babel-cli
$ npm install babel-register
$ npm install babel-preset-es2015
WebDriverのダウンロード
webdriver-managerを利用してWebDriverダウンロードする
node_modules/.bin/webdriver-manager update
node_modules/.bin/webdriver-manager update --chrome
ダウンロードされていることを確認
パスは後で使用するのでメモっておく
$ find node_modules/webdriver-manager/selenium/ -type f
node_modules/webdriver-manager/selenium/chromedriver_2.43.exe
node_modules/webdriver-manager/selenium/geckodriver-v0.23.0.exe
node_modules/webdriver-manager/selenium/selenium-server-standalone-3.141.0.jar
...
Nightwatch
nightwatchのconfigファイルを書く
事前にnightwatchに必要なディレクトリを作成しておきます。
configファイルで設定するので場所はどこでもOK!
$ mkdir tests
$ mkdir reports
公式ページの「Configuration」部分をコピーしてnightwatch.jsonに記述します。
http://nightwatchjs.org/gettingstarted
一部調整が必要なので書き換えてください。
・src_folders,output_folderに作成したディレクトリを設定
・server_pathにseleniumのパスを設定
・webdriver.chrome.driverにはwebdriverのパスを設定
$ vi nightwatch.json
{
"src_folders" : ["tests"],
"output_folder" : "reports",
"custom_commands_path" : "",
"custom_assertions_path" : "",
"page_objects_path" : "",
"globals_path" : "node_modules/babel-register",
"selenium" : {
"start_process" : true,
"server_path" : "node_modules/webdriver-manager/selenium/selenium-server-standalone-3.141.0.jar",
"log_path" : "",
"port" : 4444,
"cli_args" : {
"webdriver.chrome.driver" : "node_modules/webdriver-manager/selenium/chromedriver_2.43.exe",
"webdriver.gecko.driver" : "node_modules/webdriver-manager/selenium/geckodriver-v0.23.0.exe",
}
},
"test_settings" : {
"default" : {
"launch_url" : "http://localhost",
"selenium_port" : 4444,
"selenium_host" : "localhost",
"silent": true,
"screenshots" : {
"enabled" : false,
"path" : ""
},
"desiredCapabilities": {
"browserName": "chrome",
"marionette": true
}
},
"chrome" : {
"desiredCapabilities": {
"browserName": "chrome",
}
}
}
}
スクリーンショットを撮影するテスト作成
# スクリーンショットを出力するディレクトリは作っておいてください。
$ mkdir screenshots
# スクリーンショットを撮影したいURL一覧を作成しておく
# 今回はこのURL一覧のスクリーンショットを撮影するようにします
$ vi urls.txt
https://qiita.com/
...
$ vi tests/test.js
require('date-utils'); // 使用する場合はnpm install date-utilが必要
const fs = require('fs');
const url = require('url');
module.exports = {
'@tags': ['screenshots'],
// スクリーンショットテストケース
'screenshots': function (browser) {
// 出力先ディレクトリ
const time = (new Date()).toFormat("YYYYMMDDHH24MISS");
const outputDir = `screenshots/test_${time}`;
// URL一覧取得
const data = fs.readFileSync('urls.txt', "utf8");
const urls = data.split("\n").filter((item) => {
return url.parse(item).protocol; // URLチェック(プロトコルがあるのものだけ)
});
// スクリーンショットの出力先ディレクトリ作成
fs.mkdirSync(outputDir);
// URL一覧のスクリーンショットを撮影
urls.forEach(function(targetUrl, index) {
browser
.url(targetUrl)
.saveScreenshot(`${outputDir}/fileName${index}.png`);
});
browser.end();
}
};
Resemblejs
スクリーンショットを比較スクリプト
resemblejsを使用してスクショを比較するスクリプトを書きます
かなり雑な書き方になってしまったのでお許しを。。。
$ vi compareScreenshot.js
require('date-utils');
const fs = require('fs');
const compareImages = require("resemblejs/compareImages");
/* 実行時間 */
const nowtime = (new Date()).toFormat("YYYYMMDDHH24MISS");
/* スクリーンショットディレクトリ */
const screenshotsDir = 'screenshots';
/* レポートの出力先 */
const outputDir = `output/report_${nowtime}`;
/* 差分画像出力先 */
const outputDiffDir = `${outputDir}/diff`;
/* レポートファイル名 */
const reportFile = `${outputDir}/report.tsv`;
/* レポート項目 */
const reportItem = [
"比較ファイル1",
"比較ファイル2",
"比較結果",
"不一致率(%)",
"差分画像ファイル"
];
/* 差分ファイル名用ユニークindex */
let index = 0;
/* 画像の比較 */
async function compareDiff(filePath1, filePath2) {
const data = await compareImages(
fs.readFileSync(filePath1),
fs.readFileSync(filePath2),
{
// 設定値は好きなように調整する
output: {
errorColor: { red: 255, green: 255, blue: 0 },
errorType: "movement",
transparency: 0.2,
largeImageThreshold: 1200,
useCrossOrigin: false,
outputDiff: true
},
scaleToSameSize: true,
ignore: "antialiasing"
}
);
return data;
}
/* レポートの書き出し */
async function createReport(data, filePath1, filePath2) {
let report = [];
report[0] = filePath1;
report[1] = filePath2;
report[2] = 0;
report[3] = 0;
report[4] = '';
if (data.misMatchPercentage > 0) {
report[2] = 1;
report[3] = data.misMatchPercentage;
report[4] = `${outputDiffDir}/${index++}.png`;
fs.writeFileSync(report[4], data.getBuffer());
}
fs.appendFileSync(reportFile, report.join("\t") + "\n");
}
/* チェック処理 */
async function check(filePath1, filePath2) {
const data = await compareDiff(filePath1, filePath2);
createReport(data, filePath1, filePath2);
}
/* ディレクトリなどの準備 */
function prepare() {
fs.mkdirSync(outputDir);
fs.mkdirSync(outputDiffDir);
fs.writeFileSync(reportFile, "");
fs.appendFileSync(reportFile, reportItem.join("\t") + "\n");
}
/* メイン処理 */
function main() {
if (process.argv.length < 4) {
console.log("引数を2つ指定してください。");
process.exit();
}
const dir1 = `${screenshotsDir}/${process.argv[2]}`;
const dir2 = `${screenshotsDir}/${process.argv[3]}`;
if (!fs.existsSync(dir1)) {
console.log(`指定ディレクトリが存在しません。${dir1}`);
process.exit();
}
if (!fs.existsSync(dir2)) {
console.log(`指定ディレクトリが存在しません。${dir2}`);
process.exit();
}
const fileList = fs.readdirSync(dir1);
if (fileList.length == 0) {
console.log(`ディレクトリにデータが存在しません ${dir1}`);
}
prepare();
fileList.forEach((fileName) => {
check(`${dir1}/${fileName}`, `${dir2}/${fileName}`);
});
console.log(`チェックが完了しました! => ${outputDir}`);
};
main();
デグレ確認を行う!
nightwatchを実行し、スクリーンショットを撮影する
デグレを確認したいのでmasterと作業ブランチでそれぞれスクリーンショットを撮影しましょう
$ node_modules/.bin/nightwatch --tag screenshots
# => test_YYYYMMDDhhmmssみたいなディレクトリにスクショが出力されます
差分の出力
差分を比較したいディレクトリを指定して実行してください。
$ node_modules/.bin/babel-node compareScreenshot.js test_20181102114551 test_20181102114507
チェックが完了しました! => output/report_20181102130524
出力結果
以下みたいにtsvで差分情報が出力されます。
不一致率が0でなかったら差分があるので対象の差分画像ファイルを確認してみましょう
比較ファイル1 比較ファイル2 比較結果 不一致率(%) 差分画像ファイル
screenshots/test_20181102130429/fileName0.png screenshots/test_20181102130408/fileName0.png 1 3.29 output/report_20181102130524/diff/0.png
差分画像ファイル
差分画像は以下みたいな感じになっています。
差分のある部分が黄色く表示されていますね
qiitaのトップページとかだと広告部分が変わるので差分としてでてるのがわかります