第3回 「詳細設計書を見る人」にとっての「良い詳細設計」 CASE2(呼び出し関数) 前編

「詳細設計書」はフォーマットではなくどういう情報を載せているかが重要で、詳細設計書を見る人(コーディング者とテスト設計実施者)が質問をするようではダメだというところから、前回は「引数」に着目して「詳細設計書を見る人」にとっての「良い詳細設計」を検討しました。 今回も引き続き「詳細設計書を見る人」にとっての「良い詳細設計」を具体的に検討する第 2 回です。 「詳細設計書を見る人」でも特に単体テスト設計実施者の側から、テスト対象から呼び出されている関数「呼び出し関数」に着目して検討しています。 話題が広がったので前/後編に分けて掲載します。

今日のサンプル

一般的に良くありがちな詳細設計書(関数仕様)のサンプルとして以下を題材にしました。 なお、前回検討した引数については内容を反映してあります。

<サンプル詳細設計書(関数仕様)>
書式 unsigned char chk_date(unsigned short year, unsigned char month, unsigned char day)
仕様説明 引数に指定された年月日の範囲チェックを行い、正当かどうかをチェックする
引数 unsigned short year [入力]
意味 チェックしたい年
許容範囲 1~2100
unsigned char month [入力]
意味 チェックしたい月
許容範囲 1~12
unsigned char day [入力]
意味 チェックしたい日
許容範囲 1~31
戻り値 正常 TRUE(1) :年月日が正当
異常 FALSE(0):年月日が不当
備考

引数についてのみ追加した上記情報だけでは、まだ品質の良い単体テスト設計は出来ません。 なぜ出来ないかを順を追って検討していきます。 今回はテスト対象から呼び出されている関数『呼び出し関数』に着目します。 chk_date関数の場合、実は「正当かどうか」という部分はサブ関数chk_date_comにチェックさせています。

003-1

内部で呼び出している関数は単体テスト対象か

サンプルのchk_date関数をテストする場合、サブ関数chk_date_comは単体テストの対象に含めるでしょうか。 単体テストで必須なことは、「関数仕様」が正しく網羅されているかを確認することです。 サンプルの詳細設計には、関数の仕様として関数の「機能仕様」が書かれています。 関数仕様の中には、テスト対象関数から呼び出している関数の機能も書かれていることが良くあります。 これは実装上の仕様が書かれていないということであり、実装上の仕様を知るためにはソースを見るしかありません。 私たちは、関数仕様は「機能仕様」ではなく「実装仕様」で書かれるべきだと考えます。 関数仕様としての記載方法は一般的に次の2種類が考えられます。

機能仕様 関数のI/F以降実現しているすべての機能を対象とする仕様。 内部で関数を呼び出している場合は、その関数の機能も含まれる。
実装仕様 関数で実現しなければならない機能のみ対象とする仕様。 機能仕様との違いは内部で呼び出す関数の機能を含まず、内部で呼び出す関数の呼び方が定義されていれば良い。

単体テストは、関数単体を確認する工程なので「実装仕様」を確認すべきと考えます。

003-2

お客様からたまに「ソースコードから単体テストをして欲しい」と依頼があることがあります。 しかし、ソースコードからというのはやはり違うのではないでしょうか。 ソースコードを見て単体テストを行うということは、ソースコードが仕様書どおりの実装になっているのか分からないということです。 機能仕様が不必要というわけではありません。 実装仕様を記載している「関数仕様」と、「機能仕様」は明確に分かれているべきだと考えています。 I/Fとして外部に公開するものには「機能仕様」が適切でしょう。 この関数を呼べば(その中で呼び出す関数を含めて)この機能を実現してくれるということが必要な情報で、関数の実装に意味があるわけではないためです。 「関数仕様」は「機能仕様」を責務分担して生まれてきます。 責務分担した「関数仕様」で実装は行われるため、「機能仕様」の内容でテストしようとするとテストが出来ないということになるのです。

003-3

「機能仕様」は結合テストで、「関数仕様」は単体テストでチェックすると考えます。

呼び出し関数の機能を切り離すため呼び出し関数は無視してよいか

呼び出し関数の機能を切り離すということは、呼び出す関数は無視してしまえばいいのでしょうか。 自関数に責務がない処理は関数を呼んで処理をするため、どの処理をどの関数に任せるのかという仕様が書かれていなくてはいけません。 呼び出されている関数の仕様をはずすと関数の内部でどの関数を呼んでいるかわかりません。 結局ソースコードを見ることになってしまいます。 そのため「呼び出し関数の取り扱い」だけは記載が必要になるのです。 呼び出し関数の取り扱いについて記載があれば、呼び出す関数についてもI/Fの確認だけは出来るようになります。

003-4

詳細設計で関数設計をする際には既にモジュール分割が行われているはずです。 モジュール分割されていれば呼び出し関数もすぐにわかります。 わかっているなら詳細設計書の関数仕様には呼び出し関数の情報を記載すべきです。 呼び出し関数の情報が記載されていれば、どの処理をどの関数に任せるのかという「関数仕様」の網羅を確認できるようになります。

呼び出し関数の機能が関数仕様に含まれているときの影響

chk_date関数を例に見ていきます。 サンプルの詳細設計書で仕様説明は次のようになっていました。

仕様説明 引数に指定された年月日の範囲チェックを行い、正当かどうかをチェックする

この仕様説明は「機能仕様」で書かれているため、どこまでが自関数の責務で、どこまでが呼び出し関数の責務か境界線がわかりません。 「実装仕様」は、引数の範囲チェックを行ったら、年月日が正当かのチェックをchk_date_com関数で行う仕様になっています。

003-5

本来、chk_date_comがどの条件で呼ばれているかをテストしなくてはいけません。 chk_date_com関数を「正しいタイミング」で「正しい引数」で呼んでいるかがポイントです。 さて、サンプルの仕様説明からこのポイントをテストできるでしょうか。 サンプルには単純に「正当かどうかチェックする」と書いてあり、chk_date_comの表現は一切出てきません。 書かれていない以上、chk_date_com を呼んでいるかのテストを作成することは物理的に無理です。 作ったとしてもソースを見て差し替えが必要になります。 「機能仕様」で書かれた詳細設計書のまま単体テスト設計をすると、テスト対象関数の機能だけでは実現できないテストを設計してしまい、あとで全部作り直すことになってしまいます。 関数の仕様は「実装仕様」で書かれていることがより良い単体テストのために必要です。

あくまでも自関数の機能を設計する/テストする

詳細設計書ではあくまでも自関数の機能を設計し、単体テストではあくまで自関数の機能をテストすべきです。 塊(複数関数)で機能を成り立たせている場合、詳細設計で足りないのであれば別の単位での仕様書を作ればいいのです。 ただし、詳細設計で関数仕様を決定する時点ではモジュール分割/関数分割は行われているため、各関数における責務は明確になっているはずです。 それでも関数単体の機能が分からないのであれば、関数分割を適当に行ったと言わざるをえません。 「別の関数を呼び出してこの機能を任せる」という対象関数の責務は必要ですが、それ以外は 与える値、戻ってくる値が分かればよいのです。

呼び出される関数の引数範囲も対象関数には関係ありません。 なぜなら、呼び出される関数が引数の型分有効だと言っていても、呼び出す側が与える値が指定されていれば、その値に範囲が狭められるためです。

003-7

情報を修正してみると

機能の内容を修正してみると次の詳細設計になりました。

<サンプル詳細設計書(関数仕様) ~情報修正後~>
書式 unsigned char chk_date(unsigned short year, unsigned char month, unsigned char day)
仕様説明 引数に指定された年月日の範囲チェックを行い、範囲内の場合はchk_date_com関数で年月日が存在するかチェックする。 引数が範囲外の場合はFALSE、chk_date_com関数が正当で戻ってきたらTRUE、不当で戻ってきたらFALSEで関数を終了する。
引数 unsigned short year [入力]
意味 チェックしたい年
許容範囲 1~2100
unsigned char month [入力]
意味 チェックしたい月
許容範囲 1~12
unsigned char day [入力]
意味 チェックしたい日
許容範囲 1~31
戻り値 正常 TRUE(1) :年月日が正当
異常 FALSE(0):年月日が不当
備考

コーディング者としても関数の責務が明確になります。

今日の結論

  • 単体テストでテスト項目を作成するために「詳細設計書」を考えると情報が足りないことがある
  • 詳細設計書の関数設計では自関数の機能についてのみ記載する - 呼び出し関数についてどの関数に責務を委任するか

後編では同じサンプル詳細設計書で『呼び出し関数』の情報をどこまで記載すべきかについて検討をしていきます。

お問い合わせ

名古屋本社

東京本社

【受付時間】9:00~18:00

pagetop