30歳からのプログラミング

30歳無職から独学でプログラミングを開始した人間の記録。

なぜ E2E テストを書くのか

あまりまとまってないし、大したことは書いていない。このへんの話について知見を持っている人は、いろいろ教えて欲しい。
前提として、フロントエンドエンジニアの立場から書いている。

E2Eテストは高コストだと言われる。書くのも大変だし、メンテナンスも大変。
私はSPAを開発することが多いが、SPAをE2Eテストする場合、APIサーバをどうするのかも考えないといけない。

ではなぜ、E2Eテストを書くのだろうか。なぜ、ユニットテストだけではダメなのだろうか。

どこまで投資するかはともかく、E2Eテストは書いたほうがいいと思う。書くに越したことはない。自然にそう思う。
でもその理由を、上手く言語化できない。
しかし高いコストをかけて導入する以上、ちゃんと理由を整理しておきたい。

手間のかかる手動テストをある程度代替できるから、だろうか。
UIのあるソフトウェアを作っている人は、必ず、手動でテストすると思う。
SPAのコードをある程度書き上げたとき、それをブラウザで動作確認することなく「出来た」と見做すことはないだろう。TDDで開発していて全てのテストをパスした状態になったとしても、当然、手動や目視で動作を確認するはず。
最終成果物はあくまでも、ソフトウェアだからだ。関数やコンポーネントに対していくらユニットテストを書いても、それはあくまでも、一つ一つの部品の動作を保証したに過ぎない。ソフトウェアの動作を保証することにはならない。だから、リリースや納品の前に必ず、ユーザーと同じ環境(ブラウザやスマホなど)で、手動テストを行う。
そもそも現実的には、ユニットテストのカバレッジを100%に近づけることは困難であり、抜け漏れがあったりそもそもユニットテストが十分に書かれていなかったりする。であれば尚更、手動テストによる動作確認は必須になる。

しかし、手動テストは高コストである。いちいち人間が、実際に操作して、目視でチェックして、動作確認しなければならない。
その手動テストを、自動化出来る。それがE2Eテストを導入するメリットなのかもしれない。
つまり、最終成果物であるソフトウェアに対するテストを、ユニットテストのように自動化できるというメリット。

とはいえ、E2Eテストは手動テストの完全な代替にはなり得ない。
リリース前にはやっぱり、ちゃんと動作しているか、デグレが発生していないかを確認するために、手動でテストするだろう。
E2Eテストも所詮は人間が書いたものだから、間違っている可能性がある。そこに全幅の信頼を寄せて手動テストをしない、というのは怖い。
そもそも、E2Eテストでカバーできる範囲はたかが知れている。全てのユースケースに対してE2Eテストを書くのは、コストがかかり過ぎる。

ではなぜ、「それでもE2Eテストは書いたほうがいい」と思うのだろうか。
不完全とはいえ、これまで手動テストが担っていた役割を部分的に代替できるからだと思う。それにより、開発や運用を効率化できる。逆に言えば、この効率化以上にメンテナンスのコストがかかるなら、E2Eテストを導入する意味はない。
自分が思いついた役割は、以下の4つ。

  • 手動テストをやるほどではない変更を加えたときの安全ネット
  • ソフトウェアが壊れたときにすぐに検知できる
  • ソフトウェアに変更を加えたときの影響範囲を確認できる
  • E2Eテストを通すことが、ソフトウェアを直す際の最初の目標になる

手動テストをやるほどではない変更を加えたときの安全ネット

ここまで「手動テストをしないと不安だ」と書いてきたが、常にそういう気持ちになるわけではない。
ちょっとした変更、影響範囲を完全に把握できていると思えるレベルの変更、くらいであれば、わざわざ手動テストする必要はない。というか、そんなことで面倒な手動テストはしたくない。
例えば、マイページに表示する文言のタイポを修正した場合、そのタイポが修正されていることさえ確認すればいいわけで、マイページの各種機能が正しく動いているかを確認する必要はない。したくない。
こういうときにE2Eテストがあれば、手動テストの手間を省けるし、それでいて、動かなくなったときにそのことに気付くことが出来る。
変更による影響が心配なときは、手動テストをする。E2Eテストが活きるのは、影響がないと思われるとき。予想通り影響がないことを確認するためにE2Eテストを実行する。

ソフトウェアが壊れたときにすぐに検知できる

CIでE2Eテストを実行することで、ソフトウェアが壊れたことをすぐに検知できるという利点がある。
時間が経ってから一部のUIが動いていないことに気付くと、原因を追うのが難しくなる。だがE2Eテストなら実行のためのコストは低いので、高頻度で行うことが可能になり、破壊にすぐに気付ける可能性が高まる。

ソフトウェアに変更を加えたときの影響範囲を確認できる

E2Eテストが壊れるだろうなと思いながら破壊的変更を加えたとき、予想通りに壊れることで、変更の影響範囲に対する自分の理解が正しいことを確認できる。
予想に反して壊れなかったり、予想とは違う壊れ方をした場合は、自分の理解が間違っているか、テストが間違っている可能性がある。それにより、作業前は気付けていなかった要素に気付くことができ、開発の手戻りが少なくなる。

E2Eテストを通すことが、ソフトウェアを直す際の最初の目標になる

一度壊したソフトウェアは再び動くようにしなければならないが、E2Eテストを通すことで、少なくとも以前と同じように動くようになったことは保証できる。
E2Eテストがない場合、直ったと思う度に手動で確認し、直っていなかった場合はまたそれを繰り返すことになるが、E2Eテストを書いておけば、この確認作業を自動化できる。

***

整理すると、フロントエンドのコードに変更を加えた時の安全ネット、という感じだろうか。
E2Eテストは、意図せず壊したときにアラートを出したり、意図的に壊した時にそれを確認したりするために、書く。

そしてこの「壊した」というのは、フロントエンドのコードのことだ。バックエンドは関係ない。
そう考えると、APIはモックサーバーで十分に思える。
フロントエンドのコードが壊れてしまったことに気付けるようにするのがE2Eテストの目的なのだから、バックエンドはモックで構わないはず。

E2Eテストがコストの元を取れるかは、対象のソフトウェアによる。
シンプルなソフトウェアで手動テストが簡単に行えるなら、高いコストを支払ってE2Eテストをメンテナンスする価値はない。
ソフトウェアの運用期間が長ければ長いほど、E2Eテストがあることによる効率化が活きていくる。