ブロックチェーン企業で働くエンジニアのブログ

ブロックチェーン領域のエンジニアとして働いています

事業のどのタイミングでテストコードを書くべきか

テストコードをどこまで、どのタイミングで書くべきか、ということは悩ましい問題です。ここでいうテストコードとはプログラムコードでのテストであり、即ち自動テストに組み込む話です。テストコードがない場合は一般的に何らかの代替手段を取ります。QA(Quality Assurance)等と呼ばれるチームが手動テストを行うことで品質を担保するなどが多くあります。しかしながら、QAチームのスケーラビリティ、デグレーション(既にできていた機能ができなくなること)を防ぐためには自動テストにしていくことも重要です。

あるべきでいえば、開発コードとセットでテストコードも書くことが望ましいですし、そのような開発スタイルをとっていたこともありました。しかし、スタートアップや新規事業のプロダクト開発のような場合、エンジニアも資金も足りないリソース現場、自分たちより資本がある競合が早いスピードで機能を開発してくるようなケースも珍しくありません。

そのような場合、限られたリソースをテストを書く時間にあてるべきか、新機能開発にあてるべきか悩むパターンが出てきます。テストを書く時のスピードと品質はトレードオフではない、という論はよくでてきますが、どのような場合でも成り立つのか。新プロダクト開発の現場における確からしい選択は何なのかについて考えてみます。

前提として、自動テストはスピードをあげるもの

f:id:naomasabit:20210418234351p:plain

前提として、自動テストは開発のスピードを上げるものです。継続的に開発していく上で、デグレを防げること、プログラムが意図通りに動くことが検証されていることは開発速度を上げるために大きなメリットです。

さらに、手動テストと比べ、コードによる自動テストのメリットとして、パターンの網羅がしやすく、テストケースの抜け漏れを防げることもあります。完璧なテスト設計を行うのであればパターン網羅も可能ですが、往々にしてテストケースで想定外のデータパターンは存在します。そのようなデータパターンはプログラム内部構造を意識して境界値などの観点を組み合わせることで、データパターンを洗い出しやすくなり、コードの品質を上げることにも繋がります。

ただし、当然テストを書くということはデータパターンを網羅して、繰り返し品質を検証できるようにすることであり、一定の時間がかかります。しかしながら、「クリーンアーキテクチャ」では、このようなコードの品質を上げることが長期的にスピードに寄与し、テストを書いていたチームの方が結果的に開発スピードが早くなった、という話が出てきます。木を切る前に鋸を研いでいれば結果的に木を切り倒すことが早くなるという、木こりの寓話に通じるものがあります。

一方でリーンの検証の結果、今作っているものが商用化するとは限らない

しかしながら、自動テストを書いておくことでスピードが早くなるという条件は同じ自動テストが繰り返し行われることに基づきます。開発したコードが変化しないうちは、開発したテストも繰り返し利用されます。コードが大きく変化する場合、テストも作り直しになります。(アウトプットの結果として期待値が利用できることもあると思います)

また、リーンプロセスのような開発において、開発したコードがユーザーニーズ検証の結果破棄されるということもあり得ます。(そもそも開発しないで検証できるならそれがベストではありますが)コードが破棄されるということは自動テストも役目を終えることとなり、自動テストを書いておいた旨味はとても小さくなります。

確実に品質がリスクになるようなものはテストを書く必要がありますが、繰り返し品質を検証できる自動テストの旨味は、コードが長く続くという前提で成り立つものでもあります。

f:id:naomasabit:20210418234532p:plain

ユーザーニーズが検証されるまで、関連する機能のコードは変化が続いていくことが多いですが、検証が終わり、コードの変化が落ち着く頃はテストコードが書きやすくなります。コードの変化が落ち着いてきたものから書いていくというのは1つのパターンではないでしょうか。

しかし、新プロダクト開発の世界ではユーザーニーズ検証以外の変数として、競合が市場にやってくるなど、どうしても短期的スピードが必要で、新機能開発を優先せざるを得ない局面もあります。

技術的負債を許容してでも短期的スピードのレバレッジを効かせる局面

ユーザーニーズが検証され、コードの変化が落ち着いて来た。しかしどうしても新機能が来週までにないと売上が上がらず、競合にシェアを奪われる。このような状態で新機能開発を優先するのか、既存機能のテストコードを書いて長期的な品質を上げるのか。事業上、やむを得ず前者を選ばなければいけないケースが存在します。(品質については手動のQAなどで代替を検討します)このように、プロダクト開発において、どうしても短期的なスピードが必要な場合、技術的負債という形をとってコードに残します。

コードにバグの潜むもの、スピード重視で開発して再利用性が低いものなどは「技術的負債」と呼びます。余裕のないソフトウェア開発が引き起こす結果として生まれるとも言われます。テストコードを書かないことなどで品質が担保されないことも技術的負債の例として挙げられ、結果「利息」としてメンテナンスコストを支払い続けます。

よく揶揄される技術的負債ですが、負債とは、現実世界の事業においても成長のレバレッジをかけるためのものです。将来支払う利息分が負債に上乗せされる代わりに、現在時点で必要な資金を得て、成長エンジンとなるものに投資します。

プロダクト開発に置き換えると「今、ここ」で必要な短期的スピードを得るため、将来支払う利息の上乗せも含めて、技術的負債を許容するという考え方も論点になります。技術的負債を全面的に肯定するものではありませんが、レバレッジを効かせる側面としての負債も意識しておくと意思決定がしやすくなるかと思います。

ただし、レバレッジの効かない技術的負債は戦術上間違っていると考えた方が良いでしょう。(そもそも変数名やスコープがおかしい等はレバレッジの効かない技術的負債の代表例です)

まとめ:テストコードを書き、技術的負債を返すタイミング

テストコードを書き、技術的負債を返すタイミングについて考えていることを書きました。以下の図はこの記事で書いた1つの考え方です。

f:id:naomasabit:20210418233217p:plain

そもそも、品質が及ぼすリスクが大きいものはテストを書くべきという判断になります。(ミッションクリティカル性が高い、QAなどの代替も難しい、これが失敗するとユーザーに大きな損害を及ぼすなど)

次に、機能のユーザーニーズが検証されているのかの判断になります。されていなければ代替手段を検討も考えられるでしょう。

更に、機能のユーザーニーズが検証されて、コードの変化が落ち着いてきたかどうか。それによってテストを書くタイミングに来ているかの判断になります。ただし、技術的負債を許容してでも短期的な新規開発スピードを追い求めるかは論点になりがちです。

自動テストはスピードをあげるものだという前提は起きつつ、クリーンなコードを書いていきたいという思いを、新プロダクト開発という現場では個別状況にフィットさせる必要があります。ここに書いたのは1つの考え方ですが、ユーザーニーズとコード変化の関係性という変数も意識して個々の状況判断は行われるのが望ましいのだと思います。