SMARTCAMP Engineer Blog

スマートキャンプ株式会社(SMARTCAMP Co., Ltd.)のエンジニアブログです。業務で取り入れた新しい技術や試行錯誤を知見として共有していきます。

フロントエンドテストのはじめかた

はじめまして、もしくはまたお会いしましたね。BALES CLOUD(以下BC)エンジニアのてぃがです。
BCでは、最近フロントエンドのテストを始めました。
また、個人としても社内でフロントエンドのテストの普及啓蒙活動をやっております。
今回はこれらについてお話ししたいと思います。

※注意※

この記事で取り扱う「フロントエンドテスト」は主に「フロントエンドのユニットテスト」です。
ご了承ください。

はじめに

これまで、BCにはフロントエンドのユニットテストがありませんでした。
とはいえ、かわりにE2Eテストがあり、また、プロダクトの意品質に大きな問題もありませんでした。
しかし、BCの開発フェーズは「立ち上げ」から「機能強化」に移り変わっています。
その過程で、重要機能のまわりでちらほらとバグが見つかる、Vueのメジャーバージョンアップが必要になる(※)、などのことが起きはじめていました。

ところで、私はひとの十倍くらいの不安症です。
「石橋をたたきまくる」ように日々を過ごしているのですが、そんなエンジニアが、フロントエンドのリファクタや新規機能開発を、ユニットテストなしで実施するとどうなるでしょうか?

そうですね、不安で爆発します。

これをおりにつけてぼやいていたところ、
「じゃあつぎの半期から正式に時間取ってやってみようか!」
と上長に声をかけてもらい、「BCのフロントエンドテスト始めようプロジェクト」がはじまったのでした。

※Vueのバージョンアップについての詳細はこちらの記事が詳しい
Vue3にアップグレードしてフロントエンドを改善した話 - SMARTCAMP Engineer Blog

補記

詳細は省きますが、BC開発チームでこのプロジェクトに着手できたのには理由があります。
MISSION制と呼ばれている、
「各自がやりたい×チームが必要なことを、やりたい人が目標(※)に持って主導する」
仕組みがあったことです。
(※人事評価上の目標)

やりたいことをやって価値を出しつつ評価ももらえるって、とってもいいことです。

BCはフロントエンドのユニットテストをどう始めたのか

では、前提からあらためてお話しします。
動き始めの時点で、BCは以下のような状態でした。

  • BCはSaaSで、定期的なアップデート・機能追加が必要不可欠
  • フロントエンドのユニットテストがまったくない(E2Eはある)
  • Vue3へのリプレイスの途中である
  • 重要機能でのバグがちらほら出ているが、これをできるだけ防ぎたい

また、筆者は過去フロントエンドのユニットテストのコーディング経験がそこそこありました。
これを踏まえ、BCでは以下のような流れでフロントエンドテストを始めることにしました。

  1. 各種決め事(課題出し、目的の設定など)
  2. 手段の決定・詳細化(技術選定など)
  3. やってみる(コードを書く)

ではここからは、各ステップで実施したことをかいつまみつつご紹介します。

1. 各種決め事

プロジェクトの動き出しには「なぜやるのか」が必要です。(※諸説あり)
ということで、各種決め事をしていきます。

まずは、課題と目的を設定しました。
現状の具体的な分析と、理想など抽象的な思考を反復横跳びしつつ決めていきます。
BCでは以下のようになりました。

  • 課題
    • 開発時の開発者の不安・精神的負荷が高い
    • 開発速度を守りつつも、品質を担保する必要がある
  • 目的
    • 開発者の不安・精神的負荷を軽減し、BCとしてはやくコンスタントな価値提供ができるようにする

しかし、これでは抽象度が高いです。
理解しやすいよう、もう少し噛み砕いて具体化します。

  • フロントエンドの実装追加・変更を安全に・気楽に行えるようにする
    • BCはプロダクトの特性上、はやく・たくさん試す(PDCAを回す、失敗する)ことが求められる
    • そのための一つの手段として、主に開発者の以下の負荷を軽減する
      • システムの挙動(ロジック)が保証されていないことによる、リリースに対する不安感
      • 手動テストにかかる工数の削減
      • テストの再現性の保証

最後に、このプロジェクトの「やるやら」を決めます。
このあとのステップでの動き方を明確にするためです。
なお、「やるやら」はまず「やらない」ことを明確にすると、決めやすくていい感じです。
部分抜粋ですが以下の通りです。

  • やらないこと
    • 「見た目」(デザイン・レイアウト)に関するテスト
      • テストがあったとしても、最終的には人間の目でチェックする必要がある
      • また、実装変更でテストコードが壊れやすく保護しづらい
    • 〜略〜
  • やること
    • 「ロジックの動作を保証する」テストをかく
      • ※初期は、特に複雑なロジックについてはテストを書きたい

これらの決め事はすべてドキュメントにまとめておき、いつでも参照できるようにしました。

2. 手段の決定・詳細化

ここからはよりエンジニア的なお仕事です。
まずは技術選定をし、その後コーディングに関わるこまごましたルールを決めていきます。

技術選定については、特殊な要件がなかったためデファクトスタンダードに従いました。
これは、導入保守のしやすさなどに利点があります。

技術ベースはこんな感じです。

(今回の記事はあくまでテストの「始め方」にフォーカスしますので、これらの詳しい話は致しません。あしからず。)

その後はこまごましたルール決めですが、コーディング規約から「どういう点はテストを書いて欲しいのか?」という考え方まで多岐に渡り、どこまで決めるべきかが難しいところです。
筆者はある程度ドキュメントをだ〜〜〜っと書いたところで、この沼にハマってしまいました。
そこで弊社技術顧問に相談し、もらったアドバイスが以下です。

「ある程度決まってるから、もう動いてみて考えたら?」(※要約)

ですよね。

3. やってみる

さて、楽しい開発のお時間です。
いきなり全員に「やってくれ!」とも言いづらいので、まずは首謀者である筆者が走ってみることにしました。
「みんながテストコードを書ける」ところまでを整えていきます。

書けることはたくさんあるのですが、ざっくり紹介します。

  • 環境構築
    • 技術選定したいろいろを入れる
  • 責任を持ってサンプルコードを書く
    • 必要となりそうなテストパターンを洗い出し、該当するサンプルコードを書いていく
      • ロジックのみのテスト
      • componentのrenderのテスト
      • componentのmethod, computedのテスト
      • API callのテスト
      • などなど
  • やってみる&やってみてもらう
    • 勉強会などで基本の知識を共有
    • 準備したサンプルコードも提供

こんな感じで走り回りました。
やってみると思ったより難しくなく、急に方針転換を強いられるようなこともありませんでした。
(もちろん、こまごまとハマるところはありましたが...。)
筆者の実力というよりは、Vitestが良かったのです。
公式ドキュメントがしっかり書かれていたり、JestのコンパチなのでJestの知見が流用できたりと、救われる点は色々ありました。
公式ドキュメント大好きエンジニアとして、Vitestのドキュメントは推せます。

また、実際にコードを書くにあたって、「どこからテストを書いていくか」について追加で少しだけ決め事をしました。

  • 優先度の高いテストから書く
    • BCとして重要な機能まわりから書く
  • 書きやすいテストから書く
    • 新しく作った機能から書く

とはいえ、各ステップをどう流したのか?

ここまで各ステップについてご説明しましたが、何事もフローなので、各ステップをどう「流した」かも大切です。
各ステップごとに以下を繰り返し、物事を進めていきました。

  1. チームに匂わせ(頭出し)しつつ、首謀者がガーっとうごく
  2. チームに共有・説明
  3. チームの合意形成とフィードバックの受け取り

気をつけていたポイントは以下の通りです。

まず、チームメンバーを不安にさせないこと。
「知らない」不安感をなるべくなくすよう、情報を早い段階で共有し合意をとるよう心がけました。
一方で、「フロントエンドのテストが必要」という点も認識を合わせておいたため、全員の意見を全部聴くのではなく、動くところははやく動いて先に進めることができました。
何かあったらその時考えればよいのです。

次に、とにかくドキュメントを書くこと。
筆者は兎角忘れっぽいので、ドキュメントが好きです。
ドキュメント化することで情報は民主化されます。
後からチームに参画した人も情報を見ることができ、適宜まとめておくことで必要な情報を見つけやすくもなります。
幸いメンテナンスが必要な類のドキュメントでもないので、この時点で書いておくのはいいことづくめです。
とくに、目的や方針のドキュメントは必要でした。
進んでいく過程で悩んだときに、立ち戻って考えるポイントになりました。

最後に、「なにはともあれやってみよう!」という心意気を共有すること。
できるだけ早く価値を提供し、失敗するなら失敗してリカバリし、少しでも前に進めることを意識しました。
これは、BCで大切にしているアジャイルの考え方でもあります。
先ほども書きましたが、何かあったらその時考えればよいのです。
通常の開発だとここまで気楽にもいられませんが、これはテストの話なので、失敗したとてプロダクトが壊れるわけでもありません。

フロントエンドテストドキュメントまとめページ

そうしてどうなった?

このプロジェクトをへて、BCでは「みんながテストコードを書ける」ところまでは整いました。
テストコードも少しずつ増えてきており、テストを書く雰囲気はぼちぼちですが醸成されてきているように思います。
コードレビュー時に筆者が「ここフロントエンドテストチャンス!」などと煽って書かせているのも否めませんが(笑)

ただし、今もなお残っている課題もあります。

まず、フロントエンドのテストの正解がわかりません。
手探りに書いている感じがあります。
とはいえ「私が『これが正解だ!』とか言い出したらひっぱたいてくれ」という気持ちもありますので、これはこれでいいのかもしれません。

また、既存のコードのテストがなかなか書けません。
空き時間があればまとめて書きたいところですが、現実としてそんなものはなく、テストを書くだけのタスクを積むのは難しいです。
これは、大きめのリファクタをする前にはテストを書く、勉強会(後述)でもくもくするなどの手段で地道に対応しています。

おわりに

長々お話ししましたが、フロントエンドテストの始め方の話はこの辺で終わりです。
自ら旗を振ってやり始めたことですが、「まあなんとか軌道に乗ってよかったよかった」というかんじです。

Vueでは、Composition APIの導入によりComponentとロジックが分離される傾向にあります。
フロントエンドのテストはComposableと大変相性が良く、個人的には「今後需要も増えてくるんだろうな〜」とふくふくしております。

また、おまけ話ですが、布教活動の一環としてフロントエンドテストの勉強会を始めたりもしました。
テーマは「大人の児童館」。
フロントエンドテストに親しみ、これについて話す場の提供を目的に、社内誰でも参加OKのオンラインイベントを毎週開催しています。
毎回お楽しみコンテンツ(※フロントエンドかテストに関わっているなにか)を提供してはいます。
が、コンテンツに参加してリアクションする、もくもくする、ラジオ感覚で聴き流す、なんでもよしでゆるくやっています。

しかし、こんなことをやっていたら社内で「なんかフロントエンドの人」のような立ち位置になってきたので、ちょっと役者不足が不安ではありますが...(笑)

では、またお会いしましょう!