[[📒Productivityを上げるために大切な100のこと]] No44. 🥈
----
*この文章における見解は私の1意見であり、何か正解であるかやべき論を主張するつもりはありません。ある1開発者の思っていること..だと割り切ってご覧下さい🙇♀️*
開発をしている人なら一度は[[ユニットテスト]]を書いたことがあるだろう。そんなとき真っ先に意識する数字がある。[[コードカバレッジ]]だ。
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://ja.wikipedia.org/static/favicon/wikipedia.ico" />
<span class="link-card-v2-site-name">ja.wikipedia.org</span>
</div>
<div class="link-card-v2-title">
コード網羅率 - Wikipedia
</div>
<a href="https://ja.wikipedia.org/wiki/%E3%82%B3%E3%83%BC%E3%83%89%E7%B6%B2%E7%BE%85%E7%8E%87"></a>
</div>
[[コードカバレッジ]]0%は全くテストをしていないコードだ。一方、100%の場合は[[ユニットテスト]]が何かしらの基準ですべてのコードを網羅していることを示す。一見すると、**[[コードカバレッジ]]は高ければ高いほどいい**ように見えるが、私は==必ずしもそうとは言えない==と思っている。
## [[コードカバレッジ]]と引き換えになるもの
時間が無制限に与えられたなら、意味のある[[コードカバレッジ]]100%のコードを書けばいい。しかし、現実には時間は制限されており、**かけるコストに見合う対価を受け取れるかどうか**が焦点となる。
たとえば全ての機能において、==不具合が生じたときに人命が脅かされるなら==[[コードカバレッジ]]100%はMustと言えるだろう。むしろそこがスタートラインであり、[[コードカバレッジ]]以外の点で品質を保証できるかどうかというステージだ。
一方、不具合が発生したところで失うものが小さい機能もある。これは時と場合によるため具体例を挙げるのは難しいが..、自動運転システムを例にとるなら、**1%の確率で音楽が再生されないこと**は==1%の確率で川に飛び込むバグ==に比べれば些細なことと思える。
## 何を優先するか
私は[[ユニットテスト]]は必要だと思っている。それについて異論はない。しかし、**闇雲に100%を求めるより、クリティカルな機能に対して[[📗カバレッジ以外の目的でテストを書く]]こと** の方が大事だと思っている。それが25%なのか、50%なのか、90%なのか、100%なのか、模範解答はないだろう。
参考までに、バグが発生した場合のリスクと被害を想定した優先度をまとめてみた。もちろん、これも1つの意見に過ぎない。
- 🔴**優先度最高** (必ずテストを書く. 起こりうるパターンも全て想定する)
- 利用者に甚大な被害を与え、リカバリーが不可能なもの
- 🟠**優先度高** (基本的にテストを書く. 起こりうる代表パターンも想定する)
- 利用者に甚大な被害を与えるが、リカバリーが可能なもの
- 利用者に被害を与え、リカバリーが不可能なもの
- 🟡**優先度中** (可能な限りテストを書く)
- 利用者に被害を与えるが、普及が可能なもの
- 🟤**優先度低** (余裕があればテストを書いてもいい)
- 利用者に被害をほぼ与えないもの
これに加えて費用対効果も重要だ。コンバーターのテストと[[GUI]]アプリケーションのテストでは難易度やコストが違いすぎる。コンバーターはテストを書いた方がほとんどの場合において開発も速い。
ライブラリを開発するなら、私の経験上.. **テストを書かないと==必ず==メンテナンスできなくなる**。だからライブラリを開発し続けるなら必ずテストを書いた方がいい。
一方、[[GUI]]アプリケーションはそうとも言えない。頑張って書いたテストが大幅なUI変更で台無しになるケースも少なくない。そもそも起動しない、画面遷移しない、といったクリティカルな例だけを拾えるような[[スモークテスト]]を書けば十分だと思っている。
## 堅牢な設計はカバレッジを凌駕する
そうそう、私が開発している[[🧊Togowl]]は[[コードカバレッジ]]が2%だが不具合はほとんど発生しない。
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://github.githubassets.com/favicons/favicon.svg" />
<span class="link-card-v2-site-name">GitHub</span>
</div>
<div class="link-card-v2-title">
GitHub - tadashi-aikawa/togowl: Togowl for next generation owls :owl:
</div>
<div class="link-card-v2-content">
Togowl for next generation owls :owl:. Contribute to tadashi-aikawa/togowl development by creating an account on ...
</div>
<img class="link-card-v2-image" src="https://opengraph.githubassets.com/58dd2a620eb5a6247cb9dbbe0362fe74c5f4e6ed95bf2c4af0ebebb7d803ffce/tadashi-aikawa/togowl" />
<a href="https://github.com/tadashi-aikawa/togowl"></a>
</div>
開発手法として[[DDD]]を使っており、最も不具合の出やすいビジネスロジックでバグが発生しにくい基盤を作ったからだ。UIのバグは[[スモークテスト]]で事足りている。唯一テストをちゃんと書いているのは`utils/string.ts`という文字列を加工するクラスだ。
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://codecov.io/favicon.ico" />
<span class="link-card-v2-site-name">Codecov</span>
</div>
<div class="link-card-v2-title">
Code coverage done right.
</div>
<div class="link-card-v2-content">
Hosted coverage report highly integrated with GitHub, Bitbucket and GitLab. Awesome pull request comments to enh ...
</div>
<img class="link-card-v2-image" src="https://storage.googleapis.com/codecov-cdn/static/Codecov-icon-600x600.png" />
<a href="https://codecov.io/gh/tadashi-aikawa/togowl/src/master/utils/string.ts"></a>
</div>
[[コードカバレッジ]]を上げるだけなら1つの関数1パターンで事足りるかが、もちろんそんなことはしていない。
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://github.githubassets.com/favicons/favicon.svg" />
<span class="link-card-v2-site-name">GitHub</span>
</div>
<div class="link-card-v2-title">
togowl/utils/string.test.ts at master · tadashi-aikawa/togowl
</div>
<div class="link-card-v2-content">
Togowl for next generation owls :owl:. Contribute to tadashi-aikawa/togowl development by creating an account on ...
</div>
<img class="link-card-v2-image" src="https://opengraph.githubassets.com/58dd2a620eb5a6247cb9dbbe0362fe74c5f4e6ed95bf2c4af0ebebb7d803ffce/tadashi-aikawa/togowl" />
<a href="https://github.com/tadashi-aikawa/togowl/blob/master/utils/string.test.ts"></a>
</div>
## 『書けない』と『書けるけど書かない』は違う
最後に1つだけ。==『テストを書けない人が書かない』のと『テストを書ける人が敢えて書かない』は天と地ほど差がある==。テストを書くか書かないかの判断は、テストが書けるスキルを身につけてからでも遅くはないかもしれない。