BackstopJSを使ったCSSのリファクタリング

フロントエンド・エンジニア 郡司

皆さんはCSSをメンテナンスする際に、あるセレクターを削除したら思いもよらないページでレイアウトが崩れていたなどの経験がありませんでしょうか。サイトを運用していくに当たって、CSSのメンテナンスはサイトの構造を熟知していない人が触るとサイト全体のデザインが崩れる可能性があります。その理由として、以下が良く上げられると思います。

  • セレクターが全てグローバル変数的な扱いになること
  • 悪い意味でスタイルがカスケードをしてしまうこと
  • スタイルを消すことを恐れてスタイルの詳細度を上げて上書きしていくこと

最近、JavaScriptではJasmine、Mocha、QUnitなどテストツールが数多くありますが、CSSをテストするツールは多くはありません。その中で今回は上記の問題を解決するための手段としてサイトの見た目はそのままでCSSの構造を改善するためのリファクタリングツールをご紹介します。

BackstopJSとは修正したCSSが想定外のところで表示崩れが起きていないかグレッションテストを自動で行ってくれるツールになります。具体的には、リファクタリング前後のページのスクリーンショットを比較して、差分が出ていないかどうかを調べるツールになります。ページ全体のスクリーンショットを取ることも可能ですし、ある要素に絞ってスクリーンショットを取ることも可能になります。

導入方法

BackstopJSのプラットフォームとなるNode.jsの他に以下をインストールが必要となります。

適当なディレクトリを作成し、npmを使用した以下のコマンドを入力してBackstopJSをインストールします。

$ npm install --save-dev backstopjs

検証フロー

先ほど制作したディレクトリから ./node_modules/backstopjs に移動して以下の4ステップで検証が行えます。

  1. 設定ファイルを生成し必要な情報を記述します。
    $ gulp genConfig
  2. 比較元のキャプチャ画像を生成します。
    $ gulp reference
  3. CSSの修正を行った後、比較対象のキャプチャ画像を生成します。
    $ gulp test
  4. 規定のブラウザが立ち上がり検証結果が表示されます。

BackstopJSのサンプル

当社のWebサイトを例に実際に作業を行ってみたいと思います。

1. 設定ファイルを作成

例)設定ファイル:backstop.json サンプル


{
    "viewports": [
        {
            "name": "phone",
            "width": 320,
            "height": 480
        },
        {
            "name": "tablet_h",
            "width": 1024,
            "height": 768
        }
    ],
    "scenarios": [
        {
            "label": "knowledge",
            "url": "../../knowledge/index.html",
            "hideSelectors": [],
            "removeSelectors": [],
            "selectors": ["body"],
            "readyEvent": null,
            "delay": 500,
            "misMatchThreshold" : 0.1,
            "onReadyScript": "onReady.js"
        },
        {
            "label": "our_work",
            "url": "../../our_work/index.html",
            "hideSelectors": [],
            "removeSelectors": [],
            "selectors": [
                ".hdg_l2_2:nth-of-type(1)",
                ".lyt_col3_1:nth-of-type(1)"
            ],
            "readyEvent": null,
            "delay": 500,
            "misMatchThreshold" : 0.1,
            "onReadyScript": "onReady.js"
        }
    ],
    "paths": {
        "bitmaps_reference": "../../backstop_data/bitmaps_reference",
        "bitmaps_test": "../../backstop_data/bitmaps_test",
        "compare_data": "../../backstop_data/bitmaps_test/compare.json",
        "casper_scripts": "../../backstop_data/casper_scripts"
    },
    "engine": "phantomjs",
    "report": ["CLI", "browser"],
    "cliExitOnFail": false,
    "debug": false
}

以下にbackstop.jsonのパラメータをいくつか抜粋しました。詳細な設定についてはドキュメントをご参照ください。

viewports 検証したいスクリーンサイズを記述します。
scenarios 検証したいページの情報を記述します。
url 検証したいページのURLを記述します。
selectors 検証したいページの一部分を対象にできます。bodyを指定することでページ全体になります。
delay ページの読み込みに時間がかかるページはここを指定することでキャプチャするタイミングを変更できます。
$ gulp referenceを行うことでbackstop.jsonのurlに記載されているページのキャプチャ画像がbackstop.jsonのpathsに記載されているディレクトリに格納されます。

HTMLとCSSをわざと変更してみます。その後に$ gulp testを行うと以下のような結果が得られました。

変更前と変更後の差分が画像として表示されます。
文言のなど、細かいところまで差分として表示してくれます。

ポイントとしてページ全体のキャプチャ画像を撮ると画像の差分が全体に及ぶため、検証箇所を絞ることで精度が上がります。

用途

具体的な用途としては以下ようなシーンが上げられると思います。

  • 既存モジュールの改修による対象外ページの影響の調査
  • 単純な各ページのキャプチャ画像の取得
  • 意図した箇所のみ文言の置換が行われているかの確認

運用していくにあたって適期的にCSSのメンテナンスをしCSSの肥大化を防ぐための手段の一つであり、運用者が勇気をもってメンテナンスできるのツールの一つだと考えます。