元茹でガエルなエンジニアの記録

ちょっとやってみたことや考えたことなどを不定期に書き残していきます

テスト自動化のもたらすもの

テストコードを整備してテスト自動化を実現することで、何がうれしいのか。自分として現時点の見解を言語化しておく。
なお、自身の経験をもとにモヤモヤしていたところに、t-wadaさんの動画やpodcastによって、視界が開けたというのが正直なところです。

前提

ここでは、『テスト自動化』は、テストを自動的に実行できる状態にすることを言います。
テストコードをいつ書くのかはとくに限定せず、テストファーストテスト駆動開発でもよいし、あとからテストコードを書くスタイルでもよい。
いずれにせよ大事なことは、人手を介さず自動的(手動トリガー含む)に同じテストを繰り返し実行できる状態であることです。

テスト自動化の語彙について

テスト自動化に関してはいくつかの用語がある。 いちばん広い概念がテスト自動化で、その中でも、先にテストコードを書いてから実装に着手するやり方をテストファーストという。さらにテストファーストの中でも、あるルールに沿って小さなリファクタリングとテストを繰り返して実装を進めていく、テスト駆動開発という手法がある。

テスト駆動開発についての動画:[動画で解説]和田卓人の“テスト駆動開発”講座:連載|gihyo.jp … 技術評論社

テスト自動化の意義

もともと自分は、テスト自動化の意義は、アジャイル開発などにおける "品質の確保" だったり、毎回手動テストするのではなく自動化することで"コスト削減" すること、ぐらいのイメージで捉えていた。

つまり、開発とリリース(デリバリー)を繰り返していくとき、毎回リリース前の動作確認を手作業で実施していては追いつかないから、テスト自動化が必要になってくると考えていた。
実際にそれは正しいのだが、それ以外にもテスト自動化のメリットはある事が見えてきたので、言語化しておく。
そのひとつが、自動テスト可能なものは積極的なリファクタリングが可能になる、ということである。

テストコードがない場合、ある機能追加をしようとしたときに、設計の良し悪しではなく、単に差分の少ない方を選択してしまうことが起こりがちである。
大胆な変更による影響範囲が見えないので、変更量を少なくすることで、既存部への影響を抑えたい気持ちになる。(これを俗にdiffの小さい開発と言ったりする)

しかしテスト自動化がきちんと整備されていれば、差分の多さや構造変更を気にせずに、本来あるべき構造、正しい設計を採用しやすくなる。他の箇所への影響があったときに気付くことの出来る自動テストというセーフティネットがあるからだ。 これによって、技術的負債をため込まずに済む。少なくとも負債をため込まずに返済しやすくなる。

そうすると、長い目(とはいえ1か月で損益分岐点はおとずれるとされている)で見れば、開発のスピードを落とさずに、かつ(外部および内部)品質の高いソフトウェアを作り続けることが可能になる。 それはつまり、ビジネスにおける仮説検証や要求デリバリーのリードタイムを短縮することにつながる。

また、テスト自動化ができていれば、任意のタイミングで何回でもテストを走らせることも可能になる。
例えばスクラムで開発を進めている場合、リグレッションテストを人間が行う場合だと、どうしてもある程度タイミングを決めて、スプリントの後半でテストを実施することになる。
そうすると、デグレが発覚するのもそのタイミングになる。

一方でテスト自動化している場合は、もっと小刻みに、例えばプルリクのタイミングなどでテストを実施することも可能なので、開発の影響によるデグレをより早く検出できる。
これはいわゆるシフトレフトと呼ばれる状態で、開発してすぐにバグが見つかる方が、記憶も新しいので修正コストも低くできる。
また、デグレによる手戻りがスプリント後半で発覚すると、場合によってはスプリント内でデリバリー可能なものが出来上がらず、スプリントゴールが達成できない事態も起こりうる。 スプリントの成果物を安定してデリバリーするには、こまめな動作確認ができるほうが良い。

手動テストは無くなるか?

では、手動テストは不要になるのか、無くせるのかという点についても述べておく。 現時点の私の結論としては、無くならない。というか、無くしてはいけない。

テスト自動化が担保してくれることは、結局のところ『テストコードで書いた振る舞いが、今も変わらず同じ動きをしていること。』である。つまり、前と変わっていないということが保証されるだけといえる。

つまり、『そもそもそんな動きをするとは思っていなかった』といった未知のバグを見つけることは、テスト自動化のみでは現状はまだ難しい。したがって、そこは人間の出番となる。

人間が探索的にテストを実施し、発見したバグを再現(検出)するテストコードを追加していくことで、次回以降はそのバグは起こっていないことが保証される。

また、仕様どおりに動き、自動テストがすべて合格していても、ユーザーとしての使用感がまずいことだってあり得る。 単体機能の操作では良いものに見えていたものが、実際のユーザーとしての一連の体験の中で触れてみると、メンタルモデルとのズレによって違和感が生じる場合もある。

これからの品質保証人材には、①『具体化可能なテスト内容を自動化するスキル』と、②『具体化できない未知の不具合を見つけ出せるスキル』が必要だと考えている。

※正確には、前者のような確認をチェッキング、後者のような探索要素を持つものをテスティングと呼ぶらしいが、今回はどちらもテストと表現しています

まとめ

テスト自動化のもたらすもの
(これまでの文中に書けていない事も挙げています、すみません)

  1. テスト実施工数の削減
  2. 安定した一貫性のあるテスト実施内容の実現 (機械はミスをしないし、合格基準もあいまいではテストが書けないので、そうなる)
  3. リファクタリングに対するハードルを下げ、内部品質を高めやすくなる
  4. スプリントごとのデリバリーの安定化
  5. 外部環境の変化による動作不良の早期発見
  6. (主にユニットテスト)テスト自動化を進めていくと、自然と外部とのI/Fに依存する部分と、そうでない部分を分けていくインセンティブが働く。その結果、外部依存の高い箇所を疎結合にする設計実装のスキル獲得にもつながる