BASE開発チームブログ

フリーミアムなネットショップ構築サービス BASE( https://thebase.in )の開発チームによるブログです。開発メンバ積極募集中! https://www.wantedly.com/companies/base/projects

「お母さんも使える」サービスはどう生まれているのか? BASEのデザイン思想

f:id:lllitchi:20180711134528p:plain

こんにちは、BASEのDesign Groupに所属している北村です。
現在は主にプラットフォームとアプリのデザインを担当しています。

BASEのデザインチームはここ数年で一気に人が増え、社内でも大所帯の部署へと成長しました。今回は、BASEのデザイナーが日々の開発でどんなことを行い、どんなことを考えているのかについてご紹介したいと思います。

1. BASEのデザイナーの役割

プロジェクトの共通認識を作る仕事

BASEでは仕様検討の段階からデザイナーが入り、プロジェクトの担当者と一緒に開発要件を詰めていきます。ときには箇条書きの要件書からワイヤーを起こし、UIをアウトプットしていきます。画面デザインが先にあると、メンバー同士のコミュニケーションがスムーズになり、かつ他部署との認識合わせも円滑になるため、BASEの開発フローでは まずデザインありき という文化が浸透しています。また単純に、先にデザインがあると実際の画面をどう作っていけば良いのかチームの皆で把握しやすい、という利点があります。

プロジェクト内で共通認識となるアウトプットを担うのが、BASEのデザイナーの仕事のひとつです。

BASEにおけるデザイナーの責任

BASEでは基本的に、プロジェクトにアサインされたデザイナー本人がデザインクオリティのチェックを行います。

さらに、担当デザイナーが自分で画面のUIを実装することも多いです。最近はフロントエンドエンジニアも増えたので分業が進んではいますが、例えば細かなインタラクションの実装やUIの改修などはデザイナー自身が積極的に行っています。 画面のUIを設計するだけでなく、最終的なUXの担保まで担うのが、BASEのデザイナーの責任範囲になります。

2. BASEのデザイン思想と、大切にしていること

「お母さんも使える」という共通言語

BASEには社内全体の共通言語として「お母さんも使える」という思想が存在しています。

これは、BASE創業当時から変わらない哲学で、代表取締役CEOである鶴岡の強いポリシーであり、「BASE」の重要なコンセプトです。

というのもこのコンセプトは、「BASE」のサービス立ち上げのストーリーにまつわります。鶴岡の母は、大分の商店街で洋品店を営んでいますが、「ネットで服を売ってみたい」と鶴岡に相談があったので、楽天のような大手のECモールを使ってみるよう勧めましたが、使い方が難しくてできないと母から返ってきます。

その際に鶴岡は、母と同じような悩みを持っている人が世の中にたくさんいるのではないかと感じ、「BASE」の開発を始めた、という背景があります。

お母さんのために、良くも悪くも「機能をつけない」

便利だけれど使い方が難しい機能よりも、いかにクリック数を少なくして、簡単にショップを開設・運営してもらうかが最優先事項になります。

4、5クリックしなければならない機能より、2、3クリックで完了する機能を開発・提供する。たとえば、ユーザが一番使用する管理ページには、あえて機能をつけないなど、設計については、当初から「ユーザの手間を減らすための開発」を意識していました。

現在、BASEチームには13人ほどのエンジニアがいますが、新しい機能ができてもチーム内で「この機能は、お母さんたちには使えないのでは」となったら、たとえ便利そうな機能でもリリースしていません。

出典:お母さん目線で作ってみたら、「BASE」はシンプルなサービスになった

BASEではプロダクトの開発中、あらゆる場面・文脈で「お母さん」という単語が出てきます。「これって複雑すぎてお母さんは使えないよね」や「この説明、お母さんに伝わるのかな?」など、議論の主語となることがとても多いです。

複雑な仕組みだったとしても、お母さんも使えるくらい簡単なサービスとして提供するのが、プロダクトを作るときに最も大切にしている思想です。

誠実さを大切にしている、BASEのデザイン思想

「お母さんも使える」を実現するために、デザイナーで作成したデザイン思想があります。

f:id:lllitchi:20180711121335p:plain

  • 誠実であること
  • あらゆるユーザに寄り添える、柔軟な拡張性
  • 価値を最大化させる新しいショップ体験
  • 「お母さんも使える」親しみやすいサービス
  • 簡単じゃないものを簡単に

BASEのデザイナーはなによりも「誠実」さに重きをおいています。

例えばユーザが何かものを売りたいと思ったときに、今までだとハードルが高くて気軽にできなかったものを、誰でもできるようにするのがインターネットの力で、BASEはそのインターネットのポジティブな力を信じてサービスを作っています。

一方で、インターネットがインフラとして広まっていく上で負の側面もあり、伝え方次第では誤った情報が多くの人に広まってしまったり、誰かを傷つけてしまうことがあったりします。

そういった意味で、デザインの役割は非常に重要です。多くの人に影響を与えるインターネットというインフラ上でサービスをデザインする以上、誠実さを忘れてはいけない、という思想を大切にしています。

3. デザイン思想を実現するワークフロー

では実際に、2 のデザイン思想を実現するために行っているワークフローをご紹介したいと思います。

BASEにおけるデザインのフロー

  1. PMやディレクターから機能要件がくる
  2. 要件・仕様を元にデザイナーがワイヤー、またはプロトタイプを起こす
  3. 起こしたデザインを「UI/UXミーティング」でレビューする
  4. 実装に入る

週2回おこなわれるUI/UXミーティング

BASEでは週に2回、UI/UXミーティングという場が設けられています。 このミーティングでは、各デザイナーそれぞれが担当しているプロジェクトのUIをレビューしてもらいます。

(プロジェクトの粒度によってまちまちですが)鶴岡、PM、ディレクター、プラットフォームデザイナー、アプリデザイナー、フロントエンドエンジニア、CSが一堂に会し、デザイナーの作成したUIを見ながらみんなで議論し合います。

他のデザイナー目線でのUIに対するダメ出しも含め、ビジネス視点からの要望や、実装に対するツッコミ、全体のUXへの指摘など、多角的な意見が入ります。もちろん「そもそもその機能って必要なの?」という意見が出ることも多々あります。そこをまとめて取捨選択するのもデザイナーの役目です。

たとえ途中で仕様が変わろうとも

プロジェクトのメンバーだけでは把握できなかったより大きなユーザ体験が、UI/UXミーティングでの議論で見えてくる部分もあります。先日公開されたエンジニアの日比野柳川 の記事でも書かれていましたが、BASEではプロジェクトを進行してゆくなかで「ちゃぶ台返し」が起こるポイントがしばしば発生します。

デザイン目線でいうと、例えば

  1. 「簡単じゃないものを簡単に」が満たされてない
  2. 「親しみやすさ」が満たされてない
  3. 「価値を最大化させるショップ体験」が満たされていない
  4. 「お母さんも使える」が満たされてない

この部分の踏み込みが甘く、議論が充分でないままプロジェクトが進んでしまった時に、UI/UXミーティングで指摘を受けることも多いです。 これはBASE全体にデザイン思想が浸透しているからこそ起こる議論で、たとえもう一度仕様を練り直すことになったとしても、より良いものを作る努力は惜しまない、納得するまで議論する、というBASEの「SPEAK OPENLY」のあらわれだと思っています。

まとめ

BASEのデザイナーは裁量が多く、担う範囲も広いですが、開発の上位レイヤーから関われる環境というのはやはりやり甲斐があります。
誠実にサービスを作る、というBASEのデザイナーが大切にしている思想に共感してくださった方、一緒サービスを作りましょう!
デザイナーを随時募集しています!

jobs.binc.jp

PHPカンファレンス福岡 非公式前夜祭リジェクトコンでPHPアプリのテストスイートのカスタマイズについて発表してきました & カンファレンスレポート

f:id:tenkoma:20180615194143j:plain

こんにちは、Back-end Engineer の田中 @tenkoma です。ショッピングアプリ 「BASE」向けAPIの開発を担当しています。

去る6月16日に福岡で開催された「PHPカンファレンス福岡2018」に参加してきました。当日は一般参加でしたが、前日に開催された非公式前夜祭 リジェクトコンで発表してきたのでブログでもご紹介します。

BASEのPHPアプリケーションは2018年5月にようやくPHP7化が完了しました。 アップデートプロジェクトの中でユニットテストしやすくするためにテストスイートをカスタマイズしたので、発表で3つほどをTipsとして紹介しました。

紹介した3つのTipsについてこの記事でも説明します。

Tips 1. assertSame() で配列のdiffを出力できるようにする

PHPUnit 7 で assertSame()配列のdiff を出力できるようになりました。CakePHP2アプリ(データ形式として配列を多用する)で使えるとありがたいのですが PHPUnit 7 の利用は難しそうです。そこで、配列のdiffを出力できるように移植してみました。以下のように出力されます。

SampleTest.php

<?php
App::uses('ExtendTestCase', 'ExtendTestSuite.TestSuite');
class SampleTest extends ExtendTestCase
{
    public function testAssertArray()
    {
        $actual = ['User' => ['id' => 1, 'name' => 'Taro']];
        $expected = ['User' => ['id' => '1', 'name' => 'Taro']];
        $this->assertSame($expected, $actual);
    }
}

出力

There was 1 failure:

1) SampleTest::testAssertArray
Failed asserting that Array &0 (
    'User' => Array &1 (
        'id' => 1
        'name' => 'Taro'
    )
) is identical to Array &0 (
    'User' => Array &1 (
        'id' => '1'
        'name' => 'Taro'
    )
).
--- Expected
+++ Actual
@@ @@
 Array &0 (
     'User' => Array &1 (
-        'id' => '1'
+        'id' => 1
         'name' => 'Taro'
     )
 )

テストが失敗したときかなり原因がわかりやすくなるので、すぐにPHPUnit 7にアップグレードできない場合は以下のコードを実装すると便利です。

Tips 2. テストスイート向けにユニットテストを書く

setUp(), tearDown() などに記述したコードをどうテストするか、という話で test for test cycle(setUp/tearDown) #1 のようなテストコードを書きました。 スライドの最後で、CIで複数のPHPバージョンでテストした話をしましたが、そのためのCircleCIの設定は.circleci/config.ymlのようになっています。

Tips 3. runkit, php-timecopのコードをIDEで補完するためのスタブ

PhpStorm組み込みのスタブファイルに無いrunkit, php-timecopのようなPHP拡張のコードを補完できるようにするものです。以下のリポジトリをgit clone してIDEの include_path に追加してお使いください。

カンファレンスレポート

以下はカンファレンス当日・非公式前夜祭後夜祭のレポートです。来年も開催されるらしいので、参加したい方の参考になれば幸いです。

前日に福岡入り (6月15日・金)

PHPカンファレンス福岡を楽しむには前日入りが必須。13:30頃に福岡空港に到着しました。

このときまだリジェクトコンの資料が仕上がっていなかったので博多駅近くにとったホテルで資料の手直しをしました。

リジェクトコンの会場であるLINE Fukuoka株式会社と同じビルの1Fで知り合いの方と一緒に食事を取り、19:00 に会場到着しました。 以下、発表前の現場の様子です。

f:id:tenkoma:20180628111750j:plain

発表順は1番目。印象に残るようGitHub Username Shirtを着て発表しました。

カンファレンス本編より多い同時3セッション。だれも聞きに来なかったらどうしようと思いましたが、多くの人に聞いていただけたようです。

PHPカンファレンス福岡2018 当日 (6月16日・土)

f:id:tenkoma:20180616101153j:plain f:id:tenkoma:20180616101639j:plainf:id:tenkoma:20180616101627j:plain

PHPカンファレンス福岡は去年初参加でした。そのときは前日午前2:00くらいまで懇親会に参加した結果当日1時間以上遅刻してしまいましたが、今年は午前10時に間に合いました。

「PHPカンファレンス福岡2018」は同時2セッションです。2つの会場は両方とも席に余裕がある感じで出入りがしやすかったです。

参加したセッションについて紹介します。

MySQLで画像 を扱うメリット・デメリットと障害・解決事例

以前実装してみたことがあり、メリット・デメリットについて実感したので、さらに学ぼうとおもい参加。 発想としては思いつきがちですが、適用するメリットの大きいケースは限られそうですね。

ログの設計してますか?PSR3とログ設計の話

何をログに残せば良いかで迷うことが未だにあり、周辺知識を強化したくて参加。ログのリスクの部分を一番集中して聞いてました。

Event Sourcing,CQRS For PHP Application

複雑化するサービスのための設計パターン、アプリケーションとミドルウェアの組み合わせ例紹介。扱うデータやトランザクションが増えたり、集計分析などのシステムがあると必要とされそうに思いました。

Testing Live!!!

実際のWebサービスに対して探索的にテストを行い、問題を探すデモでした。5分という短い時間でアプリケーションに潜む不整合が見つかり、会場がすごく盛り上がってました。

PHP 5.3 + CakePHP1.3 バージョンアップ報告

去年、同じくPHPカンファレンス福岡で発表された計画の現状報告。BASE もCakePHPを利用しているので、気になりました。

物理層のこと、時々でいいから、思い出してください。

システムの物理層というより物理インフラ構築運用について面白おかしく紹介。失敗談が聞いていて面白すぎました。

その他

スポンサーブースも参加者に足を運んでもらえるようAsk The Speakerコーナー(セッション後に発表者に直接質問できる場所)とコーヒーが用意されており、いつ行っても賑わっていました。

翌日 (6月17日・日)

去年同様、株式会社Fusicのセミナールームで開催されたので参加しました。参加者各自で自由に作業しながら、発表したい人が自由に発表するようなゆるやかな集まりでした。

僕は前夜祭で発表した内容のコード tenkoma/extend-cakephp2-testsuite-example の準備をしていたのですが、飛行機の都合で2時間ほどしか参加できませんでした。

来年もし開催されるなら、絶対フルで参加できるように調整します!

まとめ

  • 非公式前夜祭 リジェクトコンで発表しました
  • PHPカンファレンス福岡、フルで楽しむなら前後のイベントもチェックしてみるのがオススメです。

スタートアップでもSIerの経験はバッチリ役に立つ~ショップコインをリリースしました~

f:id:gimutokenri:20180619154450p:plain こんにちは、BASEのPayment Engineer Groupに所属している柳川です。

先日BASEではショップコインという新機能をリリースしました。ショップコインの説明を簡単にすると、BASEをご利用いただく各ショップさんが、独自にショップで使えるコインを発行することで、ショップさん独自の経済圏を作れる機能です。詳しい説明はこちらをご覧いただけると幸いです。 私はこの機能の開発でサーバーサイドエンジニアとして設計、開発、リリースを行いました。

今回は開発者ブログの記事ということで、開発していて気がついたことをまとめてみたいと思います。

事前情報

プロジェクトの特徴

  • 修正範囲がでかい

    • 新規コード+既存の決済コードに手を入れる
    • 端的にいうと新しく決済方式を作るということ
  • 開発量に対して実装者が少ない

    • サーバーサイドエンジニア:1人
    • デザイナー:2人

私の特徴

大規模開発をしていたSIer出身。

プロジェクトの情報と私の特徴から、SIer時代の開発経験をうまく活かせば、上手にプロジェクトを回せるのではとうっすら考えながら開発に挑むのでした。

やったこと

UMLを書いた

開発が始まる前に、自分の中で以下のことを確認したいと考えUMLを書きました。

  • ヒト
  • モノ
  • コト
  • カネ

このあたりのことを詰めると、実装の漏れが防げると考えてのことでした。

SIerからスタートアップに転職してからは、関係者の人数が少ないことや、スピードが求められることからこの工程を省くことも多かったのですが、今回はそうも言ってはいられない物量であると考えてSIer時代の知識を引っ張り出してきました。このとき書いたUMLが、人に設計を共有する上でも役に立ちました。少人数で開発していると、開発中の内容がブラックボックスと化してしまうきらいがありますが、その点を少なからず軽減できたのではないかと思います。

また図に起こすことで、エンジニア以外も直感的に機能の把握が行えたようです。弊社がドキュメント管理ツールとして使用しているDocBaseにてPlantUMLの記法が使用できるため、そちらを使用してUMLを記述しました。文章でダイアグラムの作成ができるので、通常のドローイングツールに比べ、あとからの変更が非常に容易でした。おすすめです。

設計書を書いて設計書のレビューをした

転職後はあまり行ってこなかった、設計書自体のレビューをしました。

小さな機能開発であれば
頭の中や手元のメモで設計→実装→コードレビュー→リリース
この流れで、進めて大きな問題はないように思います。

しかし今回は開発量の多さが懸念されたため、SIer時代を思い返して、設計書をある程度書いて、なおかつ設計書のレビューもしようと考えました。致命的な指摘等炙り出せたので、本当にやってよかったと思いました。

ちゃぶ台返しポイントを積極的に作った

SIer時代の経験を思い出して辛いのが大幅な手戻り、いわゆるちゃぶ台返しというやつです。

残念ながら自社プロダクトの開発でもちゃぶ台返しは起こります。大切なのはいかにちゃぶ台返しのインパクトを少なくして、プロダクトのクオリティの向上に活かすか。ちゃぶ台返しは敵ではなく、味方なのです。今回はちゃぶ台返しへの対抗手段として、いろいろなところで細かくちゃぶ台返しを起こさせるという作戦を取りました。

  • 設計書のレビュー
  • 複数回のコードレビュー
  • 出来ている場所までをデプロイして操作してもらいながらのレビュー

上記のように開発期間中に数々のレビューをはさみました。

ちゃぶ台返しの回数こそ多くなったような気はしますが、結果的に工数が収まった上でクオリティを上げられたのではないかと思います。ポイントとしてはSlackでレビューを依頼をするだけではなかなか見てもらえないので、必要と思うタイミングで必要な人には明確に時間を取ってもらいレビューを行うことです。他力本願は駄目!

リリース前にQAプロセスを入れられたこと

今回少人数での開発、かつ開発量が多かったこともあり、明示的にQA期間を設け、リリース前の検証を行いました。機能の開発に関わっていないメンバーの新鮮な目で、QAをおこなってもらうのは、実際にバグが潰せるのはもちろん、精神的にも大きな助けとなりました。

うまくやれなかったこと

リリースの単位がでかくなってしまった

この発表資料を読みながら反省したのですが、リリースの単位がでかくなってしまったのは反省点かなと思います。後で確認する範囲がでかくなるだけなので、できるだけ細かく早く出すべきだったと思います。ただすぐには本番稼働しないコードを本番に組み込むのも影響確認とロールバックという点でどうだろう、というのはあるので難しいところかなとも思います。

リリース前の忙しい時期がうまく回らなかった

開発自体は、少ない人数でも段取りをしながら進めることが出来たのですが、リリース直前に立て込んでくると、開発作業とそれ以外作業の帽子をかぶり直すことが出来ませんでした。特にリリース前のQA作業を行うことと、バグを修正することを同時に行うのが厳しかったです。リリース直前に忙しくなることがわかっているなら、極力帽子をかぶり直すことなく進められるように、人をアサインしてもらうなどで準備するべきでした。

開発範囲が少ない場合は、できるだけ一人でやったほうがスピーディーに進められますが、ある程度開発範囲が大きくなると、各人が各ロールに分かれた体制を作ることに強みが出てくるのだろうなと思いました。このあたりは今後の課題かなと思います。

また、自分が今何に集中すべきかを客観的に考えるのが大切だと感じました。テンパらない。

まとめ

大きめの機能開発を、主導する立場として担当させていただき、非常に勉強になりました。まるごと任せていただけたからこその気付きが多かったように思います。特に設計書を作る、開発プロセスを明確化する等のSIerで培った技術が役に立ったのはいい経験でした。

SIer時代は、最初から決まりとしてあった開発の手順に窮屈感を感じることもありましたが、実際になんのために行うのかということを考えて、開発中の課題と照らし合わせていくと、力となる部分は無数にあるなと感じました。

当たり前ですがSIerでもスタートアップでもアプリケーションを作るという上では同じです。アプリケーション開発の道具として使えるソフトウェアの開発手法を、積極的に取り入れていくべきだと感じました。すべての開発工程が最初に描いたとおりに進んだわけではありませんでしたが、それも含めいい経験でした。忙しく開発作業を終えたあとは、知識の吸収が早い気がするので、振り返られなかった分をしっかり振り返って、学ぶべきものを見定め学んで、次に活かしたいです。日々勉強。

最後に

BASEでは、様々な経験を活かしながら一緒に未来を作っていく仲間を募集しています。前向きかつ自由にやっていけるのは間違いない環境です。 ご興味を持たれた方は以下の採用情報から!

jobs.binc.jp

リードエンジニアにおけるサービスリードという役割

こんにちは、CTOの藤川です。

これまでエンジニアの肩書において、エンジニア専門職の上級職としてリードエンジニアという役割を設定しておりました。 リードエンジニアと言うと、世間の見方としては「技術力に優れたエンジニア」というやや漠然とした役割と想像しているのではないでしょうか?

続きを読む

stylelintとBackstopJSで安全にcssを書ける環境を作った

20180605164447

こんにちは。BASE で Design Group に所属している三佐和です。主に ネットショップ作成サービス「BASE」 のフロントエンドを担当しています。

背景

BASE のデザインチームはここ最近で人数が急激に増え、活動が活発になってきており、その中のプロジェクトの一つとして、現在スタイルガイドの刷新に取り組んでいます。

しかし、人数が増えていく一方で、コーディングのルールの統一をコードレビューや個人の裁量に任せていたり、マークアップからリリースするまでに時間がかかってしまうことが問題になってきていました。 そこで、新しいスタイルガイドでは、デザイナーやエンジニアの作業工数を短縮し、より効率よく開発を進めるために、コーディングルールの整備とリグレッションテストを導入することにしました!

やったこと

  1. stylelint を使ってコーディングルールを管理
  2. BackstopJS でテストを行うことでデグレを防ぐ

前提として、 nodejs や yarn などの一般的なフロントエンド開発環境が整っているものとします。

stylelintを導入

stylelint を使って、これまで個人の裁量で保たれていたコーディング規約への準拠を機械的に行えるようにします。

導入

  • stylelintをインストール
  • その他必要なプラグイン等をインストール
  • yarn を使ってインストールします。

    $ yarn add -D stylelint stylelint-scss stylelint-order stylelint-config-standard prettier-stylelint
    

    設定

    既存のコーディングルールに合わせて、.stylelintrc を設定していきます。 BASE の場合はプロパティをアルファベット順にソートしたかったので、stylelint-order を使用したりしています。(私はいままで abc の歌を歌いながら順番にプロパティを並べていました........)

    // .stylelintrc
    {
      "parser": ["css"],
      "plugins": ["stylelint-scss", "stylelint-order"],
      "extends": ["stylelint-config-standard", "./node_modules/prettier-stylelint/config.js"],
      "rules": {
        "indentation": 4, // インデント
        "order/order": [
            "custom-properties",
            "declarations"
        ], // アルファベット順でソートする
        "order/properties-alphabetical-order": true, // アルファベット順でソートする
        "length-zero-no-unit": true, // 値が「0」なら単位を省略する
        "number-leading-zero": "always", // 小数点の頭の「0」は省略する
        "color-hex-length": "short", // HEX形式のカラーコードは3文字で表記する
        "shorthand-property-no-redundant-values": true // ショートハンドでプロパティを書く
      }
    }
    

    設定ができたら、package.jsonscripts にコマンドを追加して、 yarn lint-sass で実行できるようにします。

    // package.json
    // ...
    "scripts": {
       "lint-sass": "prettier-stylelint --quiet --write src/sass/**/*"
    }
    // ...
    

    実際の使用方法

    まずは思うがままに sass(scss) を記述します。

    .btn--submit {
        color: $white;
         background-color: $green;
     border: none;
    }
    

    めちゃくちゃですね!でも大丈夫です、lint を実行すると...

    $ yarn lint-sass
    

    こうなります。

    .btn--submit {
      background-color: $green;
      border: none;
      color: $white;
    }
    

    完璧ですね!もう歌は歌わなくても大丈夫になりました!

    結果

    常にコーディングルールを意識する必要がなくなったので、マークアップのスピードも上がりました!

    2. BackstopJSを導入

    BackstopJS を使って、戻りが発生しないよう、動作チェックする仕組みを作ります。

    導入

    • BackstopJSをインストール

    stylelintと同様に、yarn を使ってインストールします。

    $ yarn add -D backstopjs
    
    • backstop.json にオプションを設定し、スナップショットを撮る
    • スナップショットを使ってテストする

    設定

    backstop.json に必要なオプションを設定していきます。

    // backstop.json
    {
      "viewports": [
        {
          "label": "sp",
          "width": 320,
          "height": 480
        },
        {
          "label": "pc",
          "width": 1024,
          "height": 768
        }
      ],
      "scenarios": [
        {
          "label": "reference", // スナップショットの名前
          "url": "テストするURL",
          "hideSelectors": [],
          "removeSelectors": [],
          "selectors": [
            "#test-sandbox" // スナップショットを撮影する部分
          ],
          "readyEvent": null,
          "delay": 500,
          "misMatchThreshold" : 0.1,
          "onBeforeScript": "",
          "onReadyScript": ""
        },
        {
          "label": "test", // スナップショットの名前
          "url": "テストするURL",
          "hideSelectors": [],
          "removeSelectors": [],
          "selectors": [
            "#test-sandbox" // スナップショットを撮影する部分
          ],
          "readyEvent": null,
          "delay": 500,
          "misMatchThreshold" : 0.1,
          "onBeforeScript": "",
          "onReadyScript": ""
        }
    
      ],
      "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,
      "casperFlags": [],
      "debug": false,
      "port": 3001
    }
    

    設定ができたら gulpfile にタスクを追加します。

    // gulpfile.coffee
    // ...
    exports.backstopref = () =>
      connect.server({root: './build', livereload: true})
      backstopjs('reference').then () ->
          connect.serverClose()
    
    exports.backstop = () =>
      connect.server({root: './build', livereload: true})
      backstopjs('test').then () ->
          connect.serverClose()
    // ...
    
    
    

    そして、package.jsonscripts にコマンドを追加して、 yarn backstop-ref で参照用画像の作成、 yarn backstop-test でテストが実行できるようにします。

    // package.json
    // ...
    "scripts": {
        "backstop-ref": "gulp backstopref",
        "backstop-test": "gulp backstop",
    }
    // ...
    

    実際の使用方法

    はじめに、テストの元データになる参照用の画像を作ります。

    $ yarn backstop-ref
    

    20180605170855

    BackstopJS は、この画像をもとに比較テストを行ってくれるので、予期せぬ変更を行ってしまった場合にテストが失敗し、それに気づくことができます。

    試しに、このボタンの border-radius8px から 0px へ変更してみましょう。 そしておもむろにテスト実行用のコマンドを叩きます。

    $ yarn backstop-test
    // ...
          compare | ERROR { requireSameDimensions: false, size: isDifferent, content: 0.32%, threshold: 0.1% }: reference bbq_reference_0_test-sandbox_0_sp.png
          compare | ERROR { requireSameDimensions: false, size: isDifferent, content: 0.32%, threshold: 0.1% }: test bbq_test_0_test-sandbox_0_sp.png
          compare | OK: reference bbq_reference_0_test-sandbox_1_pc.png
          compare | OK: test bbq_test_0_test-sandbox_1_pc.png
           report | Test completed...
           report | 2 Passed
           report | 2 Failed
           report | Writing jUnit Report
           report | Writing browser report
           report | jUnit report written to: ~~/backstop_data/ci_report/xunit.xml
           report | Resources copied
           report | Copied configuration to: ~~/backstop_data/html_report/config.js
          COMMAND | Executing core for `openReport`
       openReport | Opening report.
           report | *** Mismatch errors found ***
          COMMAND | Command `report` ended with an error after [0.51s]
          COMMAND | Error: Mismatch errors found.
                        at ~~/backstopjs/core/command/report.js:113:17
                        at <anonymous>:null:null
    
          COMMAND | Command `test` ended with an error after [5.371s]
          COMMAND | Error: Mismatch errors found.
                        at ~~/backstopjs/core/command/report.js:113:17
                        at <anonymous>:null:null
    
    [15:02:59] 'backstop' errored after 5.38 s
    

    差分が発生したので、テストが失敗し、レポート用の HTML が出力されました。

    20180605164934

    これを開いてみると、差分のある箇所がピンク色になっています!分かりやすいですね!

    結果

    作業を開始する前にスナップショットを作成しておくことで、行った作業でのデグレに早く気づいたり、防ぐことできるようになりました。

    まとめ

    今回、stylelintやBackstopJSを利用したことで、実装者の負担が以前よりも軽くなりました!

    実装者が増えても差分が生まれにくく、デザインの一貫性を保つことができる仕組みを考え、引き続きスタイルガイドを作成していきたいと思います。また同時に、それらをメンテナンスしやすい環境も整えていきたいと思います!