テストは開発者を助けるためのデバッグツール
皆さんはテストに対してどういったイメージを持っているでしょうか?
私は今まで(何を隠そう)テストを一ミリも書いたことがなかった人間です。ここ1年くらいでテストを書き始めたのですが、今までテストを書いてこなかった理由は「書くのがめんどくさい」「書いてる人は幻想だと思っていた」からです。
テストは必要だとわかってはいるが、テストを書く工数を考えると手で確認した方が早いし、ブラウザ確認してやれば確実だと思ってました。
「まず、テストをするにしても何をテストするのか?🤔」
どうテストを書けばいいかも何か基準があるわけではないと感じ、どこから始めていいかも分からない。実装したものを確認すれば特に過不足もないし、テストに対する問題意識は持っていましたが書こうとはしていませんでした。
というか別にみんな書いてないし動いてたら必要ないと思っていて、テスト書くのは幻想だと思ってました。
今ちょこちょこテストを書くようになってきて、私も少しですがテストに関してなんとなく道筋が見えてきた感があるので共有していきたいなーと思います。
私がテストを書くうえでの伝えたいメリットは3点です。
- 小さなスコープでの開発が可能になる
- 1度書いてしまえば何度も確認してくれる奴隷(デグレの検知)
- 実装をいろんな角度で実験できる
他にもあるかも知れませんが、この3つが今は便利な点かなと思います。
それぞれざっくりこういうところが便利だよというところをまとめていこうと思います。
小さなスコープでの開発が可能になる
例えば、モーダルとその中のUIを操作するコンポーネントを作るような状況があったとして、私ならおそらくこんな感じで進めると思います。
- まず、モーダルとその中に表示するコンポーネントの表示部分を適当に作る
- 実装対象のページに配置する
- モーダルを開けるように state を調整したり、操作用のボタンなどを仮実装して配置
- ブラウザで正しい状態になっているかを確認する
- 適宜ブラウザで確認しながら、必要な実装を追加していく
実装の状況によって前後することはありますが、大体このような流れで進めています。
ただし、テストがない状態だと困る場面があります。
たとえば、モーダル内に表示したいコンポーネントが実装できたか確認しようにも、ページに配置したり、モーダルを用意して開けるようにしたりと、導線を整えてからでないと確認できません。
せっかくモーダルの動線を実装して表示確認したのに、そのとき初めて「中の表示がちゃんと動いてない!」と気づくと、そこからさらに原因を探してデバッグしなければならず、まだ見たいものを確認できてもいないのに時間だけがかかってしまいます。
この点で、StorybookやJestは非常に役に立ちます。
モーダルの中身だけを切り分けpropsを渡して表示・確認・実装できるからです。
レイヤーを分けて書けるので、コンポーネントが完成していなくても、propsを直接渡すだけで動作確認ができます。必要な処理が未実装でも、mockを用意しておけばそのままテストが進められます。
正直、今回のように「モーダルを表示するだけ」のようなケースなら、ページに配置してpropsを固定値で渡しておけば、ブラウザでも十分確認しながら進められるとは思います。
ですが、仮に「途中までの実装でPRを出したい」となったとき、一時的な表示確認用のコードをプロダクトに入れて確認し、レビュー時にそのコードを削除する……といった手間がどうしても発生します。
テスト環境を使えば、プロダクトコードに影響を与えることなく、途中の状態を切り分けて確認することができます。
これは言葉で説明してもなかなか伝わりづらいですが、やってみると実感できるはずです。
小さくマージできるのは正義です。
モーダル部分だけでも先に実装して、「動いているか」「想定通りの見た目か」などを小さなスコープで確信を持って進めたいなら、テストはほぼ必須です。
私にとってテストは、一時的な確認コードを安全に残しておける“デバッグ環境”のようなものでもあります。 後で消す前提でもいいですし、プロダクトコードではないのでTODOを雑に残しておくのも自由です。
さらに、「動くテスト」を残しておければ、後述するような場面でもそのまま活用できますし、何より開発の安心感が全然違います。
Info: ちなみに、テストがあればブラウザでの確認がまったく必要ないということではありません。
1度書いてしまえば何度も確認してくれる奴隷(デグレの検知)
挙動確認するまでに様々な操作が必要なものであれば、確認するだけでもだいぶ時間がかかります。その結果何度も確認ばかりで実装があまり進んでないみたいな状況がたまにあります。
実装途中であっても、実装後であってもテストコードは残しておくことができます。テストがあると他の実装をしてコードを修正をしたとしても、その確認を行う時間を省略して正しさを検証してくれます。
今の機能が動いているかどうか、テストコードがない状態で判定するのはめんどくさいです。
そうした中でコードを修正するとなると他の機能が壊れていないと確認することができません。
(えいや!)と直した後、実は他のところが壊れていたとなってしまうと修正のためにまた直す必要が出てきて、思い出しながら実装するとなると時間も無駄です。
動いているかの確認に人力を使って人海戦術で調べるよりも、喜んでタダ働きしてくれるテストさんに肉体労働させた方が自分が楽できます。
チームとしてもテストコードがあることによってメリットもあります。
- どういった機能になることを期待しているのかが書かれていてコンポーネントの使われ方を想像できる
- 周辺の実装を修正しても他の機能がテストで動いていることを確認できるので確認の手間を省ける
- 修正したことによって壊れることが判明してくれればバグの検知ができる
- 機能が動いているとテストコードの確認とテストの結果である程度判断できる
いいことづくめです。(^Д^)
むしろ最近はテストコードがない方が「なんでテストコードがないの?😡」と迷惑に思うことすら増えました。他の人に迷惑をかけないという意味でも皆がテストを書く意識は持っておいた方が親切かなと思います。
実装をいろんな角度で実験できる
テストはブラウザで人間か確認するよりも圧倒的に早いので、いろいろな検証を一気に行うことができます。
たとえば「ここにif足したらどうなるだろ?」、「こういう入力値だと登録できるのか?」など疑問に思ったことに対してのどうなるかの検証ができます。
初めて使うライブラリやコードの理解を深めるためのサンプルコードの実装や既存で実装されているコードにこういう操作するとどうなるのかなど、ブラウザでもbreak pointをセットしてデバッグしたりできますが、テストでも同じようにbreak pointを設定してテストできます。
無理に完璧を目指さなくてもいい
まとめると、小さくマージするために、分割した単位で開発が可能でデバッグしながら作っていける、テストを書けば後で何か実装を変えることになっても正しいと検証できるのがテストをする利点だと私は思います。
ではテストを全てのコードに対して考えていかないといかないのかと言われるとそうではないと思います。
みたらすぐわかるみたいなことならテストコードを書くではなくStorybookでビジュアルリグレッションテストするためのコンポーネント作るでも良いし、何をどうテストするかに関してはある程度最終的な結果の部分をテストできてさえいれば細かいところのテストを書いてなくてもなんとかなる気がします。
テストがあればコードを生きた状態で残しておけるのでソフトウェア開発において継続して開発することが何より大事なように、テストも少しづつ継続して前に進め続ける変化に対応できるようにするためにテストが必要かなーといった体感です。
皆がいつか来るそのコードの改修に自信を持てたり、修正の手助けになったり、意図せず壊すことをなくして楽をするために書くスタンスを持って臨むのが大事かなと思ってます。
最後に:さぁ君も始めてみようテスト実装 🎵
フロントエンドは最終結果がブラウザで表示されていてそのブラウザの要素に対してテストができるのである程度テストがしやすい部類な気がします。
バックエンドのテストを書いたことはないですが、バックエンドだとロジックの結合次第ではmockばかりでテストしづらいものもある気がしますが、フロントだと表示されていたりするため最終的な結果だけを判定できるのでテストがしやすいのかなと思います。
また、最近はCopilotも優秀なので自動でテストも書いてくれますし、境界値テストやエラーケースのテストなども自動で書いてくれるので、あとはそれを確認して修正するだけでテストが書けるようになってきています。
何より、テストがあればこここうなってたから気をつけないとなみたいなことを考えなくても、テストがあるから大丈夫だろうと安心して実装に集中できるようになります。
なので、テストは書いておいて損はないです。
テストを書くのはめんどくさいし効果を実感できるのはだいぶ先になるかも知れませんが、テストはレガシーな環境のコードでも書けます。
始める敷居を高く感じてしまうと勿体無いなと思うので手頃なところや実装したものからテストを書いてみるのが良いんじゃないでしょうか?
私ごとですが、現在は大規模なフロントエンドのコードをテストするためにPlaywrightを使ってE2Eテストなんかを書こうかなーと模索しているところです。ここら辺の戦略とか知見みたいなのはまた別の機会に書いていこうかなと思います。
テストをやろうと思って一から一気に書くからしんどいです。とりあえず不安だなと思うところやすでに仕様や実装がわかっているところやここは大事みたいなところからテストを書いていくのが良いんじゃないかなと思います。
ワイ的参考になった書籍や資料をいくつか紹介しておきます。