単体テスト 勘所
〇はじめに
まず個人的な経験なのですが、下記に近い依頼の受け方をしたことがあります。
「A,B,Cの3つの関数を単体テストして欲しいんだけど、C0/C1でカバレッジ100%で頼むよ。ツールはWinAMSで宜しく。それと100%いかなかった場合は理由の記載もお願い。」
こういったときに「(こいつこの殿方は何言ってんの・・?)」
と思うわけです。(基本情報すら持っていないレベルで仕事してすみません)
当然いつものように罵声を浴びせられながらの聞き込みを終え、完了はできたのですが・・。
さすがに毎回この程度の質問をするのは周りに申し訳ないなー(ホントだよ?)と思いつつ、「単体テスト?何それ?」な初学者に向けてこのような惨劇は繰り返してはならん!という記事です。
〇記事の内容
・そもそも単体テストとは
・カバレッジとは
・テスト自動化ツールとは
・スタブとは
・テストケース作成の定石
〇単体テストとは
(一般的に)1つの関数を対象に、コーディングミスを発見するためのテスト。
実施観点としては、ブラックボックステストとホワイトボックステストに分けられる。
ブラックボックステスト・・INPUT、OUTPUTが所望の値となっているか(仕様ベーステスト)
ホワイトボックステスト・・ロジックや型のサイズ、処理の順番など間違っていないか(構造ベーステスト)
〇カバレッジ(コードカバレッジ)とは
簡単に言うと**「所定の網羅条件がテストによってどれだけ実行されたかを割合(%)で表したもの」**という理解で差し支えないと思います。
<補足(長いからとばしてもいいよ)>
限られた工数の中で、開発しているソフトウェアのコードに対し、
信頼性や品質を確保するためのテストを実施するには「どの程度テストを実施したか」を表す指標が必要になりました。このテスト実施具合の指標を数値化して表したものをコードカバレッジと言います。
コードカバレッジを測定することで、テストによって対象のプログラムコードがどれだけ実行されたかを判定し、テストの実施率を評価することが可能になります。また同時に、テストが実施されていない命令文や分岐文を確認することができるため、未検証のコードや不用なコード、及び不足しているテストデータを早期に発見し、品質向上につながるテストを実施することが可能になります。
テストを実施するにあたって、カバレッジ (網羅率)を測定/分析することは、
ソフトウェアの品質向上に非常に大きな意味を持ちます。
なぜなら、カバレッジ情報からテストそのもの品質を定量的に測ることができるからです。
テストのカバレッジを測定する方法は、コードや仕様、要件、設計など、
さまざまな側面から計測する方法がありますが、単体テストの段階では、
コードベースのカバレッジでテストの品質を測ることが一般的です。
コードカバレッジを測定し、テストが実施されていないコードを確認することにより、テストの妥当性を向上させることができます。
〇C0/命令網羅/ステートメントカバレッジ
【指針】全ての実行文を1度実行すればOK
→if文のelse側に処理がなければ、else側の判定は実施しない。
【保証できる内容】
・コーディングしたが実行されない実行文はない
・存在してはいけない実行文はない
〇C1/判断文カバレッジ/判定条件網羅/ブランチカバレッジ
【指針】全ての条件文の真/偽を実行すればOK
→if文のelse側に処理がなくても、else側の判定は実施する。
【保証できる内容】
・存在してはいけない実行パスは存在しない
〇C2/単純条件カバレッジ/コンディションカバレッジ
【指針】全ての条件文の条件式の組み合わせを1度実行すればOK
【保証できる内容】
・存在してはいけない条件判定式の要素がないこと
例)条件式(X and Y) or Z
→全ての条件文の条件式の組み合わせを実行
→条件要素に対する網羅性は100%だが、効果のないテストが含まれてしまう!
〇MC/DC:Modified Condition/Decision カバレッジ
【指針】全ての条件文の条件式の組み合わせのうち、意味のある組み合わせを全て1度実行すればOK
【保証できる内容】
・C2と同等の網羅内容(テストデータはC2より少ない)
他の条件式の真偽を固定して、1つの条件式の真偽を変化させたとき、
全体の条件に変化があるものだけを実行する**「下表Yのみ実行対象となるように」**
C2の網羅性を維持して、テストパターン数を抑えることができる
<補足>
Yのテストケースを左から順に①②③④とすると、
①と②でZを評価
①と④でXを評価
③と④でYを評価
〇その他カバレッジ
行カバレッジ ・ ブロックカバレッジ ・ パスカバレッジ ・ 関数カバレッジ ・ コールカバレッジ
→とりあえずは、こういうのがあるんだなーくらいで。
〇単体テスト自動化ツール
WinAMS・・組込みソフト単体テスト、カバレッジ計測ツールのデファクトスタンダード。
機能安全規格ISO26262(ISO:国際標準化機構) / IEC61508(IEC:国際電気標準会議)に準拠。
〇スタブ作成の考え方
funcA{ A=funcB(); if(A!=0){ 処理1 }else{ 処理2 } }
funcAが対象のテスト。
funcBはきっと他のところでテストされているはずだし、
その正しさまで検証するのは funcA の責務ではない!!
なので、今はfuncAの正しさだけに注目すべき!
そのために funcB_stubとしてテストのために決まりきった
「正しい」挙動をするオブジェクトを注入します。
すると、テスト内でfuncB_stubは正しい動きをするとわかっているわけなので、
もしテストが失敗したとしたら「他のどこか」ではなくfuncAの実装に問題があるとわかるわけです。このように、テストを書くときは他のオブジェクトの実装に依存しないテストを作るべきです。
このために作成するのが「スタブ」です。
funcB_stubでの戻り値を固定で「0」とそれ以外の値「3」などを
設定することC1の条件が満たせる。(スタブはツールで作れるのでここでは概念だけです)
〇さいごに
いくつか例題で考え方を示せたら分かりやすいのかな・・
改善点あればご意見おねしゃす!