fc2ブログ

ユニットテストとアサーションをどう扱うのか?

 事前条件、事後条件、不変表明をチェックするためにアサーションを使用する技法が一般化しています。これは防御的プログラミング/攻撃的プログラミングの一種であり、趣味と実務の違いを如実に表していると思います。というのも、初心者用のプログラミング本ではかかれないものの、多くのプロが実務で使用しているからです。初心者用のプログラミング本で書かれていないので、初心者やアマチュアはアサーションの重要性が分からないと思いますが、実務でアサーションの使用が一般化しており、それは非常に重要な技法だと考えて下さい。
 初心者のために簡単に説明すると、バグを減らすために使用する技法です。大体こんな感じでアサーションを使用します。

#include <assert.h>
int foo( int value ) 
{
    int result;

    //事前条件
    //引数は0以上でなければならない
    assert( value >= 0 );
    
    //何らかの処理をして戻り値を導出する
    result = value;

    //事後条件
    //返す値は-1以上でなければならない
    assert( result >= -1 );

    return result;
}

int main()
{
    //制約違反!
    //foo( -10 );

    //OK
    foo( 0 );
    return 0;
}

これはC言語を使った非常に簡単な例です。実務でこの様な関数は使用しませんが、雰囲気は伝わると思います。
 テストにはもうひとつ、有名かつ頻繁に利用される技法があります。それは、ユニットテストです。大半の人がユニットテストを書いている事でしょう。特にJavaプログラマは殆どの人がJUnitを使用していると思います。
 ここで一つの疑問が生じます。アサーションとユニットテストをどのように扱うのかです。アサーションを使用した技法は一見、ユニットテストと相性が合いません。事前条件、事後条件、不変表明の3つのチェックをソースに一切書かず、テストプログラムに記述すれば可読性が向上して良いと考える人がいても当然です。特にJavaや.NET系の言語は例外処理を使用する事もあり、アサーションをどのように使用するのか悩む人が多いでしょう。
 私も悩んだのですが、今は両方の技法を使用した方がいいと結論付けています。その理由は設計意図とテストプログラムは別種のものだからです。プログラムに設計の意図を書くのと、テストプログラムを書くのは別の意味を持っている行為です。
 まず、アサーションの方ですが、これは設計の意図を示すものです。ただ単にエラーが発見できればいいというものではなく、設計者の意図を示すのが本意です。関数もしくはメソッドがどういった制約を持つのかは、明らかに設計に属する事柄なのです。
 一方、テストプログラムはバグの撲滅が本意です。テストプログラムを書くと、自然とオブジェクトデザインが明らかになったりしますが、それは副次的な効果であり、テストはバグをなくすために行う行為です。むろん下手なインタフェースはバグの元であり、テストとオブジェクトデザインは無関ではありませんが、だからと言って両方を詰め込むのは頂けません。集団作業で本来の意味とは違うものを詰め込むと、コミュニケーションを阻害する恐れが高いです。コミュニケーションに支障が生じると、バグの発生件数が多くなるのは言うまでもないでしょう。
 以上の考えから私は、設計の意図とテストを明確に分離するために、2つの技法を併用しています。ただし、プリプロセッサを併用しなくてはなりません。それが少し美しくないのですが、アサーションを使用した報告機能を用意しておくと、万が一運用時にバグが生じても解決が速くなるので利点があります。運用時に1つのバグもないのが理想ですが、絶対安全神話を唱えずに、もしバグがあっても解決できるように準備しておくのが当然だと言えるでしょう。
 この話題に限らず、分離性は大事だと時だと私は考えております。物事を分離しておく方が明瞭かつ単純に保てます。先の事を考えるのであれば、明瞭であるべきだというのが私の持論なのです。この記事が誰かのお役にたてば幸いです。

※注意:.NETの場合はアサーションではなくコードコントラクトを使用するべきです。
スポンサーサイト



テーマ : プログラミング
ジャンル : コンピュータ

コメントの投稿

非公開コメント

プロフィール

インドリ

Author:インドリ
みなさん、はじめまして、
コンニチハ。

ボクは、無限の夢(infinity dream)を持つネタ好きな虹色の鳥インドリ(in dre)です。
色々な情報処理技術を啄ばむから楽しみにしてね。

http://twitter.com/indori
は別人による嫌がらせ行為です。
私とは関係ないので注意して下さい。
次はなりすましブログなどをするかもしれませんが、ここ以外でブログをするつもりがないので、ここ以外にインドリのブログがあったとしても無視してください。


何度言っても分からない人がいるので、ここにコメント欄へ書き込むときの注意事項を書きます。


一、社会人としてのマナーをわきまえましょう。
一、妄想に基づく書き込みを止めてください。
一、暴言の類は書かないで下さい。
一、某誹謗中傷サイトの書き込みは彼らの妄想に基づく書き込みですから無視して、ここへ書き込まないで下さい。
一、コメント書く前に他のコメントよく読んでから行って下さい。
一、言いがかかり等の行為を禁止します。
一、その他常識的に考えて迷惑なコメントはしないで下さい。


以上のルールを守れない人のコメントは削除します。



利用上の注意
ここに紹介してある文章およびプログラムコードは正確であるように心がけておりますが、内容を保証するものではありません。当サイトの内容によって生じた損害については、一切の責任を負いませんので御了承ください。


執筆したCodeZineの記事


【VB.NETで仮想CPUを作ろう】

  1. VB.NETで仮想CPUを作ろう
  2. レジスタの実装
  3. 仮想CPUのGUI化
  4. テストドライバの改良
  5. CPUの基礎動作の実装
  6. MOV命令の実装
  7. ADD命令実装
  8. SUB命令実装
  9. INC命令&DEC命令の実装と命令長
  10. MLU命令の実装とModR/Mについて
  11. DIV命令の実装とイベント設計について
  12. 機械語駆動式 関数電卓を作ろう!
  13. 機械語駆動式 関数電卓を作ろう! 解答編(前半)
  14. 機械語駆動式 関数電卓を作ろう! 解答編(後半)


【仮想ネットワーク実装でTCP/IPを学ぼう】
  1. TCP/IPの基礎と勘所
  2. ネットワークアクセス層の勘所
  3. インターネット層の勘所
  4. トランスポート層の勘所
  5. アプリケーション層の勘所
  6. セキュリティの基礎と仮想ネットワークの仕様
  7. GDI+と独自プロトコルの定義



【並列化】
インテル Parallel Studioを使って並列化プログラミングを試してみた
並列プログラミングの効率的なデバッグを実現する「Parallel Inspector」


【TBBシリーズ】
  1. インテル スレッディング・ビルディング・ブロックの概要
  2. インテルTBBから学ぶループの並列化
  3. スレッドセーフとインテルTBBのコンテナ
  4. インテルTBBのスレッドクラス


【OpenMPシリーズ】
  1. OpenMPの基礎構文
  2. OpenMPの実行時ライブラリと並列ループ
  3. OpenMPのメモリモデルとfork- joinモデル

最近の記事
最近のコメント
月別アーカイブ
カテゴリ
Ada (9)
COBOL (5)
C (9)
C++ (11)
C# (370)
D (25)
Java (8)
Perl (1)
Ruby (14)
PHP (2)
Boo (2)
Cobra (2)
LISP (6)
F# (33)
HTML (0)
XHTML (0)
CSS (0)
XML (0)
XSLT (0)
Scala (4)
WPF (0)
WF (2)
WCF (0)
LINQ (4)
MONO (5)
Linux (0)
MySQL (0)
ブログ内検索
リンク
最近のトラックバック
RSSフィード
ブロとも申請フォーム

この人とブロともになる

QRコード
FC2カウンター