今回は、新人エンジニアが「単体テストの考え方/使い方」の第一章を読んだので、備忘録としてまとめてみました。今後、読書録シリーズの続編も出す予定です(予定です)。
では、早速本題へ→
chap.1 なぜ単体テストを行うのか?
単体テストを書くうえで、テストにかける労力をできる限り抑え、テストから得られる効果を最大限に引き出すことが重要。
- 労力と効果のバランスを取るためには、良いテストと悪いテストを見分けることが必要
- 費用対効果を分析する
- 状況に応じた単体テストのテクニックを使う
- アンチパターンを避ける方法を知る
単体テストの現状
単体テストの実施は当たり前。捨て去られること前提のプロジェクトでない限り、必ず書かれる。
- 現在の課題は、「単体テストを書くべきか」ではなく「良い単体テストを書くとはどういう意味か?」
なぜ、単体テストを行うのか
単体テストは、ソフトウェア開発を、持続可能なものにするために行う。
- テストを書かずにプロダクト開発を続けると、コードが劣化しすることによって「ソフトウェアエントロピー(無秩序)」が増加し、コードへの信頼がなくなり、いずれ開発が止まってしまう。しかし、単体テストがあれば、一部のコードの変更による「退行(regression)」を検出することができるため、安定した品質を担保することができる。
- 単体テストの唯一のデメリットは、テストを書く「労力」である。しかし、開発初期からテストを書くことで、「持続のしやすさ」と「成長のしやすさ」を備えることができ、長い目で見て「適切な開発スピード」を維持できるようになる。
*退行: 特定の変更をした後、意図したように動かなくなること。バグ。
何がテストの質を良くし、何がテストの質を悪くするのか?
単体テストはただ書けば良いのではなく、「質の良い」テストを書かなければいけない。たとえば、テストに時間がかかりすぎたり、退行を検出できなかったり、保守コストがかかりすぎた理、間違った理由でテストが失敗することが増えすたりれば、テストの存在によって、プロダクト開発の進行が脅かされる。
また、テストコードの保守コストは、以下のような作業の積み重ねで増加する。
- プロダクションコードのリファクタに伴い、テストコードをリファクタすること
- プロダクションコードを変更するたびに、テストを実施すること
- テストが間違って失敗したとこに、その対処をすること
- プロダクションコードがどのように振る舞うかを理解するために、テストコードを読むこと
網羅率とテスト・スイートの質との関係
網羅率:テストケースが実行するプロダクションコードの割合
一般に、網羅率は高いほど良いとされるが、「高ければ良い」わけではない。
- たとえば、網羅率10%であれば、テストが十分でないことがわかるが、網羅率100%だからと言って、テストの品質が良いとは限らない。
コード網羅率と分岐網羅率について
コード網羅率 : プロダクションコードの総行数に対する、テスト時の実行行数。実行されたコードの行数÷総行数
分岐網羅率 :プロダクションコードの分岐路に対する、テスト実行時に経由される分岐の数。経由された経路の数÷分岐経路の数
網羅率の問題
-
網羅率からは、実際にテスト対象のコードが検証されたのかを保証できない
- 網羅率は、プロダクションコードが「実行された割合」を示すため、その結果が検証されたことを保証していない。
- 確認不在のテスト:プロダクションコードを実行しているにも関わらず、結果を検証していないテストコード
import pytest def example(num): if num < 5: return "short" else: return "long" def test_example(num): actual == example(num) # プロダクトコードを実行
-
網羅率を算出する際、使用するライブラリなのコードは計測の対象から外れる
網羅率まとめ
網羅率は、「テストが十分に行われていないこと」を検証するための数値であり、「良いテストであること」を保証するものではない。加えて、高い網羅率を義務付けるような使い方をすると、かえって開発の妨げとなる可能性が高い。
何がテスト・スイートの質を良くするのか?
テストケースの良し悪しを、定量的に自動で判断する方法は存在せず、結局のところ、1つずつ個人が判断するしかないが、優れたテストスイートの特徴を挙げることは可能である。
-
テストすることが開発サイクルに組み込まれている
→ コードが変更されるたびに、テストを実行する必要がある -
コードベースの、特に重要な部分のみがテスト対象になっている
→ プロダクションコードのうちの重要な箇所(ドメイン・モデル、ビジネスロジック)のみに、テストの労力をかけることが重要 -
最小限のコストで、最大限の価値を生み出すようになっている
→ 上記には、以下が必要
* 価値のあるテストケースを認識できること
* 価値のあるテストケースを作成できること
感想
個人的に、「テストすることが開発サイクルに組み込まれている」ことが重要だなと感じています。
元々、私が参画しているプロジェクトでは、ユニットテストを書いていませんでしたが、テストを書く習慣がついてからは、予期せぬバグが減ったのはもちろん、自分自身のコードへの理解力が上がったり、プロダクションコードを綺麗に書こうという気持ちが強くなったりしました。
この本の概要を理解できたら、使っているテストフームワークの勉強を体系的にしてみたいなと思ってます。