単体テスト(ユニットテスト)を舐めるな(WF開発)
SESで4年働いた人の感想です。
単体テストとは何か
単体テストは、開発フェーズやテストフェーズで最初に実施されるテストです。ソフトウェアの最小単位とされていますが、その「最小単位」の定義はケースによって異なるため、この理解で問題ないと考えています。なお、当記事はWF型の開発を前提としています。
具体的な手法について
- 機能確認テスト
各モジュールが外部設計(SW方式設計)に基づいて正しく機能しているかを確認します。 - 制御フローテスト
順次、分岐、繰り返しの網羅を行います。 - データフローテスト
データが「定義」→「使用」→「消滅」の順に正しく動いているかを確認します。
PJの現実
PL「今回の改修案件は影響範囲が大きく、デグレが心配です。なので全網羅します。」
リーダーA「時間がありませんが、品質上げるためにも全網羅しましょう!」
リーダーB「カバレッジを100%でお願いします。」
あくまでも複数の現場を経験した私の経験のお話ですが、これがPJの現状です。
全網羅すれば品質は100%担保されますが、組合せ爆発が生じるため、非常に時間がかかり非効率です。カバレッジとは具体的にどのレベルを指すのか、疑問が残ります。
この状態で上長の指示通り全網羅やテストしようとすると、下記のリスクが考えられます。
- メンバー間の認識の違いにより、品質がバラバラになり、後工程で故障が多発するリスク(残業も増えるかと思います)
- 結合テストで見つかったバグが単体テストの漏れとして扱われ、プロジェクト全体の評価が下がるリスク
時間がないからこそ、テストの進め方を考えて計画を立てる必要がありますが、納期が迫っていたり、お客様からの圧力があると、冷静な判断ができず不適切な指示が出されることがあります。
なのであなたが軌道修正する必要があります。
※単体テストごときでテスト計画は不要という意見もありますが、私が言いたいのは、システムテストのような詳細な計画書を作成する必要はなく、30分の打ち合わせを通じて単体テストの進め方を共有してほしいということです。
なぜなら、一般的に全工程のうち製造・単体テストが全工程の約3割を占めると言われており、単体テストだけでもある程度時間がかかるとされています。たった30分のチームでの認識合わせでリスクを減らせるにもかかわらず、多くの現場ではこのプロセスが議論されていないと感じます。エンジニアとマネジメントの両方から、単体テスト工程が軽視されている印象を持っています。私は、これは炎上を防ぐための最後の防波堤だと考えています。
では、どうすればよいのか
結論としては後戻りを防ぐ方法を検討します。
-
前提
テスト関連が要件定義されていれば、その方法でテストを実施します。
他の案件での過去実績があればそれを参考にすると、上長を納得させる材料にもなります。ただし、明確なルールがない場合や非効率な方法は参考になりません。 -
戦法1:テストしながら製造する。そして、ソースコードの理解しやすさと複雑度を低くすることを意識する。
製造工程と単体テスト工程が分かれている場合、単体テスト時に製造内容を確認する手間が増えます。忘れない範囲でテストケースを記載しながら製造することで、作業効率が向上します。経験のあるメンバーは、テストを意識しながら製造することで品質を高めます。(TDDでもいいです)
また、テストコードを作成する場合でも複雑度が高いソースコードに対してだとテストコードの製造に手間が増えます。単純に複雑なソースほど、考慮漏れの可能性も増えて障害発生する確率も増えるのでいいことがないです。
経験あるメンバーは内部設計されていなそうなエラー時の考慮を行い、後戻りを少なくしましょう。 -
戦法2:C2カバレッジを100%にし、コストメリットを主張する。
時間が許せばMCCのカバレッジを100%にしてください。しかし、ほとんどのPJではC2カバレッジ100%を目指すことが現実的な落としどころです。合わせて、戦法3に記載する機能確認テストのケース作成に力を入れてください。MCCで実施するテストを機能確認テストで実施することでテスト効率を高めるイメージです。
上長も”カバレッジ100%”という数字を得られるため、現実的な落とし所となります。 -
戦法3:基本の3技法で機能確認テストを行う
残念ながらC2カバレッジを100%にしても、当たり前品質には達しません。機能確認テストでコンポーネントの品質を向上させます。このテストは入力に対する出力結果を確認するだけなので、結果が明確です。また、ソースではなく外部設計書を基にテストケースを作成できるため、経験が浅いメンバーでも参加しやすいです。実は単体テストレベルだと、ホワイトボックスのテストケースよりも作成しやすいのです。
時間が足りない場合は、単体テストより後工程での障害1件あたりの後戻りコスト増加のデメリットを主張して時間を貰いましょう。
基本の3技法というのは境界値テストと同値クラステスト、そして異常系と特異値のテストです。
経験豊富なメンバーが異常値や閏年など特異なケースを考慮すると、見落としのリスクが減ります。
※業務系アプリなど、ワークフローごとに静的変数(static)を初期化する処理を作成した場合、追加でデータフローテストを行う必要があります。システムテストでもユースケースを組み合わせた一連のテストでは、漏れが生じる可能性が高いため、単体テストの段階で変数の初期化漏れを解消しておかないと、本番環境で問題が発生するリスクが高まります。
- 戦法4:結合テストレベルのテストを単体テストで実施する(ケース不要)
設計による問題や考慮漏れを早期に見つけるために、モジュールを結合してシナリオに沿ったテストや複雑な操作を行います。あくまでも単体テストであり、結合テストではないため、詳細なケースは不要です。もし障害が発生した場合は、ケース外として課題管理表に記録する運用になるイメージです。
単体テストの後の工程で障害が見つかると、バグ1件に対してチケット作成やレビュー、お客様への報告が必要になり、コストが増大します。そのため、設計ミスや考慮漏れはできるだけ早く発見することが重要です。早期に問題を見つけることで、対策の選択肢も広がります。
この戦法は、納期が迫っているプロジェクトに特に効果的です。外部インターフェースの仕様の誤解などが原因で、結合テストが始まったのにテストが進まないといった事態を防ぐことができます。
本質的な問い
要件定義段階で単体テストの品質についてユーザーと取り決めを行わない理由は何でしょうか。
生命に関わるシステムや金融システムではMCCでのテストが必要な場合もありますが、企業のキャンペーンサイトではホワイトボックス自体が不要な場合もあると思います。
ビジネス視点での判断材料を持っていない現場が判断するのは本質的には間違っていると考えています。
Discussion