TOP>>ツアー>>チュートリアル(DBアプリ編) 概略<ツアー>OBAQ構成定義アプリケーションサーバリファレンスサイトマップ

テストファーストプログラミング


テストファーストプログラミング

WalrusにはXP(eXtreamPrograming)の「テストファースト」という手法を支援する機能があります。

テストファーストとは、メソッドの実装をする前に、 単体テストルーチンを実装することです。 そして、それ以降、プログラムの修正をするたびにテストを行なって確認していくわけです。 これを確実に実施すれば、プログラムは常に従来の機能を満たした状態で進化していくことになるので、 究極の品質が得られるという考え方です。

目新しい考え方ではありませんが、これまではこれを実践するのは困難でした。 特にGUIのプログラミングでは、プログラムを動作させるのにユーザのオペレーションが必要になります。 これを自動化するためには、GUIのイベントを発生させるツールが必要になり、 大変困難でした。

Walrusでは、GUIの見た目の部分がHTMLテンプレートという形で独立しており、 プログラムのロジックは言わゆるビジネスロジック、実際にデータベースを参照したり更新したりする部分に限られています。 そのため、GUI=ユーザ介入なしに単体テストを行なうことが容易です。

RUBYUNITとWalrusの連動

下記のような構成定義ファイルを記述することで、 バッチモードのWalrusからRUBYUNITによるテストを実行することができます。

%require obaq/runit

Folder test
  UriageEntry uriage -- table_name=Uriage

TestCaseObj test1
.def test_uriage1 { 
  # テスト1
}
.def test_uriage2 { 
  # テスト2
}

WalrusCommandSet test -- default
 RunTest test1

この構成定義ファイルには、Walrus/Obaqのオブジェクトを含めることができますので、 テストデータの作成や印字も連動させることが可能です。

テストデータの作成

OBAQのオブジェクトには、データベースにデータを入力する機能があります。 これを使用して、テスト実行の前にテストデータを入力するようにします。

TableData shohin {
1 "Programing Ruby" 1000
2 "Programing Perl" 2000
3 "Programing Python" 3000
4 "Programing Walrus" 4000
}

DBScript insert_shohin {
  app.get_object(TableData, :shohin).each do |d|
    r = Shohin.new_wrapper_object(*d)
    dbconn.exec r.insert_sql
  end
}

WalrusCommandSet all
 DoScript insert_uriage
 RunTest test1

このようにして、毎回テストを実行する前に、一旦全てのデータを削除してから、 各テーブルのテストデータを再設定します。 そうすれば、テストが必ず同じ環境で実行されるようになります。

テストルーチンの作成

次に、テストルーチンを作成します。 例えば、売上データの商品コードが存在しない場合に例外が発生するか確認するには、 次のようなテストスクリプトを作成します。

f = app.get_object(Folder)
u = f.get_object(Path::create("uriage"))
req = Request.new("", "get", "", {}, nil)
sess = u.create_request_processor(req)
sess.setup

r = Uriage.new_wrapper_object

r.tanto_code = 7654
assert_exception(RuntimeError) { sess.check_data(r) }

get_objectやcreate_request_processorはオンラインモードのWalrusで内部的に使用されるメソッドです。 詳細はリファレンスやコードを参照してください。

check_dataは、標準ドキュメントオブジェクトEntryで、データを追加する直前に呼ばれるテンプレートメソッドです。 カスタムアプリケーションでは、このメソッドを再定義して、 必要なチェックを行ない、データに問題がある場合は例外をraiseします。

そこで、ここではRubyUnitのassert_exceptionを使用して、 例外が発生することをチェックします。

テストルーチンの実行

このようにテストルーチンを作成したら、 本体を作成する前にこれを実行して、エラーを検出することを確認します。

$ walrus test_uriage.wal
.....
Time: 0.475479
FAILURES!!!
Test Results:
 Run: 2/2(3 asserts) Failures: 1 Errors: 0
Failures: 1
test_uriage.wal:47:in `test_uriage2': 
  expected:<10> but was:<0> (RUNIT::AssertionFailedError)
.....

これから、本体のプログラムを作成して、Failures:とErrors:の値が0になれば、 プログラミング(と単体テスト)が完了したことになります。


ページトップへ