<commit_before>---
title: "ブラウザでビジュアルテストをするreftest-runnerを作った"
author: azu
layout: post
date : 2015-05-14T09:02
category: JavaScript 
tags:
    - Testing
    - Browser
    - JavaScript
    - Node.js

---

## 概要

[reftest-runner][]というブラウザで描画内容やレイアウトといった表示結果をテストするためのライブラリを作りました。

要素技術としてはブラウザ、WebDriver API、レンダリングキャプチャ、画像Diffという感じです。

- [azu/reftest-runner](https://github.com/azu/reftest-runner "azu/reftest-runner")

### 時間が無い人向け

以下のスライドに簡単に[reftest-runner][]やreftestとはなにか、どういうユースケースがあるのかが書いてあります。

- [reftest-runner-overview.pdf](https://github.com/azu/reftest-runner/tree/master/docs "reftest-runner-overview.pdf")

## reftestとは

reftest(Referrence Test)とは、2つのHTMLの表示結果(スクリーンショット)を比較することで表示結果が意図したものかをテストする方法です。

用意するHTMLとして以下の2種類を1セットとして用意して利用します。

- テスト用HTML
	- テストしたい機能を使って実装したHTML
- リファレンス用HTML
	- テスト用HTMLとは別の機能で実装したHTML

この2つのHTMLをブラウザで表示し、スクリーンショットを取って画像として比較することで、2つのHTMLの表示が一致する OR 一致しないことを自動的にテストするためのツールが今回作った[reftest-runner][]です。

![ref-test](https://cdn.rawgit.com/azu/reftest-runner/master/docs/reftest-runner-overview-image.png)

詳しくは以下でも書かれていますが、FirefoxやWebkit、Chormeといったブラウザで使われていて、こういうのをもっと普通のウェブ開発レベルでも使いたくなったのでこれをインスパイアしています(完全に一致というわけでもないかも…)

- [リファレンステストの書き方 by nakajmg](http://slides.com/nakajmg/reftest#/ "リファレンステストの書き方 by nakajmg")
- [Writing Reftests | Test the Web Forward](http://testthewebforward.org/docs/reftests.html)
- [Creating reftest-based unit tests | MDN](https://developer.mozilla.org/en-US/docs/Creating_reftest-based_unit_tests)
- [w3c/csswg-test](https://github.com/w3c/csswg-test "w3c/csswg-test")

reftestは、画像のキャプチャを保存しておいて比較するのと違って、HTMLがテストファイルとなっています。
そのため、reftest向けに作ったHTMLは自動テストだけじゃなくて、普通にHTMLを開いて目視のテストや機能のデバッグなどにも使えるので多少面倒ですが意外と使い道があったりします。

また画像自体を保存して画像比較するテストは管理が大変なので、reftestのような形式のほうが柔軟性がある感じです。

> 画像比較ベースのテストは変化に弱く保守が大変なので、 一年ほど前に Reftests と呼ばれる新しいタイプのテストがサポートされた
> -- [炭坑の庭師 - steps to phantasien](http://steps.dodgson.org/b/2012/05/20/gardening-with-canaries/ "炭坑の庭師 - steps to phantasien")

## reftest-runnerのできること

- HTMLの描画結果の比較テスト
	- いわゆるreftestができます
	- 非同期テストも対応しています
- クロスブラウザの描画比較テスト
	- 通常は同じブラウザ同士で別HTMLの表示比較をしますが、同じHTMLを別ブラウザで表示比較が可能
	- WebDriverサポートしてるブラウザ - IE、Firefox、Chrome、Safari、Opera、PhantomJSなどで動作します
- 比較結果のDiff画像を生成
- テスト結果をTAP形式で出力
- テスト用のローカルサーバを立てる
- `reftest.list` という形式でテスト対象を記述
[reftest-runner][]はrunnerという名前になってて一応コマンドラインツールとしても動かせますが、本質的にはNodeモジュールとして使えるような作りになっています

Diff画像とは以下の様なテスト対象とリファレンスのキャプチャ画像を比較して差分を出す画像で、[yahoo/blink-diff](https://github.com/yahoo/blink-diff "yahoo/blink-diff")を使っています。

![diff](http://efcl.info/wp-content/uploads/2015/05/2015_05_13__08-54-18-canvas-left.html-vs-canvas-right.html2.png)

この画像の差が一定のしきい値(delta、設定可能)を超えると一致してないと判定されます。

表示結果さえあれば何でもテストできるので、テストが難しいCanvas APIのテスト等もできます。

---

## インストール

```
npm install reftest-runner -g
```

でインストールできます。インストールすると`reftest-runner`というコマンドが追加されます。

## 動かし方

リポジトリにサンプルが入ってるので、このreftestを動かしてみたいと思います。

- [reftest-runner/example at master · azu/reftest-runner](https://github.com/azu/reftest-runner/tree/master/example "reftest-runner/example at master · azu/reftest-runner")

先ほどでてきて`reftest.list`というテキストファイルに、比較するHTMLと比較演算子(== or !=)を並べるのが簡単な使い方です。

サンプルの`reftest.list`では以下のようになっています。

```
# implementation is difference, but visual is the same
== ./equal/smile-canvas.html ./equal/smile-img.html
# ◀ != ▶
!= ./non-equal/canvas-left.html ./non-equal/canvas-right.html
# async test support
== ./async/reftest-async-xhr.html ./async/reftest-sync.html
```

例えば、

```
== ./equal/smile-canvas.html ./equal/smile-img.html
```

は`./equal/smile-canvas.html`と `./equal/smile-img.html`の描画結果が一致することを期待する ということを示しています。

この作成した`reftest.list`をCLIで以下のように指定すれば、reftestが実行できます。

```
$ reftest-runner --list path/to/reftest.list
```

もちろん、`reftest.list`なしでもできて、以下のようにテスト用ファイルとリファレンスファイルをそれぞれ指定することでも実行できます。

```
$ reftest-runner --browser "firefox" --targetA path/to/fileA.html --targetB path/to/fileB.html
```
<commit_msg>Update 2015-05-14-reftest-runner.md<commit_after>---
title: "ブラウザでビジュアルテストをするreftest-runnerを作った"
author: azu
layout: post
date : 2015-05-14T09:02
category: JavaScript 
tags:
    - Testing
    - Browser
    - JavaScript
    - Node.js

---

## 概要

[reftest-runner][]というブラウザで描画内容やレイアウトといった表示結果をテストするためのライブラリを作りました。

要素技術としてはブラウザ、WebDriver API、レンダリングキャプチャ、画像Diffという感じです。

- [azu/reftest-runner](https://github.com/azu/reftest-runner "azu/reftest-runner")

### 時間が無い人向け

以下のスライドに簡単に[reftest-runner][]やreftestとはなにか、どういうユースケースがあるのかが書いてあります。

- [reftest-runner-overview.pdf](https://github.com/azu/reftest-runner/tree/master/docs "reftest-runner-overview.pdf")

## reftestとは

reftest(Referrence Test)とは、2つのHTMLの表示結果(スクリーンショット)を比較することで表示結果が意図したものかをテストする方法です。

用意するHTMLとして以下の2種類を1セットとして用意して利用します。

- テスト用HTML
	- テストしたい機能を使って実装したHTML
- リファレンス用HTML
	- テスト用HTMLとは別の機能で実装したHTML

この2つのHTMLをブラウザで表示し、スクリーンショットを取って画像として比較することで、2つのHTMLの表示が一致する OR 一致しないことを自動的にテストするためのツールが今回作った[reftest-runner][]です。

![ref-test](https://cdn.rawgit.com/azu/reftest-runner/master/docs/reftest-runner-overview-image.png)

詳しくは以下でも書かれていますが、FirefoxやWebkit、Chormeといったブラウザで使われていて、こういうのをもっと普通のウェブ開発レベルでも使いたくなったのでこれをインスパイアしています(完全に一致というわけでもないかも…)

- [リファレンステストの書き方 by nakajmg](http://slides.com/nakajmg/reftest#/ "リファレンステストの書き方 by nakajmg")
- [Writing Reftests | Test the Web Forward](http://testthewebforward.org/docs/reftests.html)
- [Creating reftest-based unit tests | MDN](https://developer.mozilla.org/en-US/docs/Creating_reftest-based_unit_tests)
- [w3c/csswg-test](https://github.com/w3c/csswg-test "w3c/csswg-test")

reftestは、画像のキャプチャを保存しておいて比較するのと違って、HTMLがテストファイルとなっています。
そのため、reftest向けに作ったHTMLは自動テストだけじゃなくて、普通にHTMLを開いて目視のテストや機能のデバッグなどにも使えるので多少面倒ですが意外と使い道があったりします。

また画像自体を保存して画像比較するテストは管理が大変なので、reftestのような形式のほうが柔軟性がある感じです。

> 画像比較ベースのテストは変化に弱く保守が大変なので、 一年ほど前に Reftests と呼ばれる新しいタイプのテストがサポートされた
> -- [炭坑の庭師 - steps to phantasien](http://steps.dodgson.org/b/2012/05/20/gardening-with-canaries/ "炭坑の庭師 - steps to phantasien")

## reftest-runnerのできること

- HTMLの描画結果の比較テスト
	- いわゆるreftestができます
	- 非同期テストも対応しています
- クロスブラウザの描画比較テスト
	- 通常は同じブラウザ同士で別HTMLの表示比較をしますが、同じHTMLを別ブラウザで表示比較が可能
	- WebDriverサポートしてるブラウザ - IE、Firefox、Chrome、Safari、Opera、PhantomJSなどで動作します
- 比較結果のDiff画像を生成
- テスト結果をTAP形式で出力
- テスト用のローカルサーバを立てる
- `reftest.list` という形式でテスト対象を記述
[reftest-runner][]はrunnerという名前になってて一応コマンドラインツールとしても動かせますが、本質的にはNodeモジュールとして使えるような作りになっています

Diff画像とは以下の様なテスト対象とリファレンスのキャプチャ画像を比較して差分を出す画像で、[yahoo/blink-diff](https://github.com/yahoo/blink-diff "yahoo/blink-diff")を使っています。

![diff](http://efcl.info/wp-content/uploads/2015/05/2015_05_13__08-54-18-canvas-left.html-vs-canvas-right.html2.png)

この画像の差が一定のしきい値(delta、設定可能)を超えると一致してないと判定されます。

表示結果さえあれば何でもテストできるので、テストが難しいCanvas APIのテスト等もできます。

---

## インストール

```
npm install reftest-runner -g
```

でインストールできます。インストールすると`reftest-runner`というコマンドが追加されます。

## 動かし方

リポジトリにサンプルが入ってるので、このreftestを動かしてみたいと思います。

- [reftest-runner/example at master · azu/reftest-runner](https://github.com/azu/reftest-runner/tree/master/example "reftest-runner/example at master · azu/reftest-runner")

先ほどでてきて`reftest.list`というテキストファイルに、比較するHTMLと比較演算子(== or !=)を並べるのが簡単な使い方です。

サンプルの`reftest.list`では以下のようになっています。

```
# implementation is difference, but visual is the same
== ./equal/smile-canvas.html ./equal/smile-img.html
# ◀ != ▶
!= ./non-equal/canvas-left.html ./non-equal/canvas-right.html
# async test support
== ./async/reftest-async-xhr.html ./async/reftest-sync.html
```

例えば、

```
== ./equal/smile-canvas.html ./equal/smile-img.html
```

は"`./equal/smile-canvas.html`と `./equal/smile-img.html`の描画結果が一致することを期待する" を事を示しています。

この作成した`reftest.list`をCLIで以下のように指定すれば、reftestが実行できます。

```
$ reftest-runner --list path/to/reftest.list
```

もちろん、`reftest.list`なしでもできて、以下のようにテスト用ファイルとリファレンスファイルをそれぞれ指定することでも実行できます。

```
$ reftest-runner --browser "firefox" --targetA path/to/fileA.html --targetB path/to/fileB.html
```

{'fraction_non_alphanumeric': 0.1322942161535489, 'fraction_numerical': 0.01365451500708489, 'mean_word_length': 6.1822386679000925, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 14, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '962593', 'n_tokens_mistral': 5046, 'n_tokens_neox': 4542, 'n_words': 305}