ビヘイビア駆動とかよく分からないけど、とりあえずRSpec書きながらプロシージャを作ってみる #1
とりあえず簡単なプロシージャをRSpec書きながら作ってみようと思います。
どんなの作るん?
PROCEDURE get_message( iv_message_code IN Messages.message_code%TYPE, iv_token1 IN Messages.token1%TYPE, iv_token2 IN Messages.token2%TYPE, iv_token3 IN Messages.token3%TYPE, iv_token4 IN Messages.token4%TYPE, iv_token5 IN Messages.token5%TYPE, ov_message OUT VARCHAR2 );
iv_message_codeにメッセージコードを入力すると、対応したメッセージ文字列が返ってくるようなプロシージャです。テーブルを以下のように設定しておき
message_code | message | token1 | token2 | token3 | token4 | token5 |
MES100000 | 私の名前は &NAME です。 | &NAME |
get_message( iv_message_code => 'MES10000', iv_token1 => 'もっこす', ov_message => lv_message )
てな感じでプロシージャを実行すれば「私の名前は もっこす です。」とlv_messageに突っ込まれるイメージです。簡単すぎてすんません。。
とりあえずRSpec書いてみるか(ノープラン)
# # messagesテーブルに保存されたメッセージを返すPL/SQLプログラムを # RSpec書きながら作ってみるテスト # require 'rubygems' require 'spec' require 'oci8' # # テスト対象のPL/SQLプロシージャ # (こんな感じのプロシージャ作る) # PROCEDURE get_message( iv_message_code IN Messages.message_code%TYPE, # iv_token1 IN Messages.token1%TYPE, # iv_token2 IN Messages.token2%TYPE, # iv_token3 IN Messages.token3%TYPE, # iv_token4 IN Messages.token4%TYPE, # iv_token5 IN Messages.token5%TYPE, # ov_message OUT VARCHAR2 ); # target_plsql = <<-PLSQL BEGIN get_message(:iv_message_code, :iv_token1, :iv_token2, :iv_token3, :iv_token4, :iv_token5, :ov_message); END; PLSQL # # データベース接続用変数 conn = nil # describe "トークンを指定せずにメッセージを取得するとき" do before(:all) do # テスト前準備 apxe/apxe@xeでデータベースへ接続 conn = OCI8.new('apxe','apxe','xe') end after(:all) do # データベースからログオフ conn.logoff end it "(1) SELECT message FROM Messages WHERE message_code = 'MES000000'で「正常終了しました。」というメッセージを取得できる" do cursor = conn.exec("SELECT message FROM Messages WHERE message_code = 'MES000000'") cursor.fetch.should == ["正常終了しました。"] end it "(2) 「MES000000」を指定すると「正常終了しました。」というメッセージを取得" do cursor = conn.parse(target_plsql) cursor.bind_param(':iv_message_code', 'MES000000') cursor.bind_param(':iv_token1', '') cursor.bind_param(':iv_token2', '') cursor.bind_param(':iv_token3', '') cursor.bind_param(':iv_token4', '') cursor.bind_param(':iv_token5', '') cursor.bind_param(':ov_message', nil, String, 2000) cursor.exec cursor[':ov_message'].should == "正常終了しました。" end end
既にデータベースにMessagesというテーブルを作成し、一つメッセージを登録してあるので(1)のテストは成功します。でも、まだプロシージャを作っていないので(2)のテストは下記のようにコケます。
トークンを指定せずにメッセージを取得するとき - (1) SELECT message FROM Messages WHERE message_code = 'MES000000'で「正常終了しました。」というメッセージを取得できる - (2) 「MES000000」を指定すると「正常終了しました。」というメッセージを取得 (ERROR - 1) 1) OCIError in 'トークンを指定せずにメッセージを取得するとき (2) 「MES000000」を指定すると「正常終了しました。」というメッセージを取得' ORA-06550: 行2、列3: PLS-00201: 識別子GET_MESSAGEを宣言してください。 ORA-06550: 行2、列3: PL/SQL: Statement ignored stmt.c:539:in oci8lib.so /Library/Ruby/Site/1.8/oci8.rb:759:in `exec' /Library/Ruby/Site/1.8/oci8.rb:142:in `do_ocicall' /Library/Ruby/Site/1.8/oci8.rb:759:in `exec' ./get_message_spec.rb:60: Finished in 0.134598 seconds 2 examples, 1 failure
(1)のテストはdescribeの文章的には無い方がよさげですが、そもそもデータベースにテストデータ入ってるんかいという確認が欲しかったので付けました。
そういうわけで、(2)のテストを成功させるべくプロシージャを書いてみましょう。
プロシージャを書く
テストを成功させるために最小限のプロシージャを書きます。
CREATE OR REPLACE PROCEDURE GET_MESSAGE( iv_message_code IN Messages.message_code%TYPE, iv_token1 IN Messages.token1%TYPE, iv_token2 IN Messages.token2%TYPE, iv_token3 IN Messages.token3%TYPE, iv_token4 IN Messages.token4%TYPE, iv_token5 IN Messages.token5%TYPE, ov_message OUT VARCHAR2 ) AS lv_ret_message VARCHAR2(2000); BEGIN SELECT message INTO lv_ret_message FROM Messages WHERE message_code = iv_message_code; -- OUT変数にMessagesから取得した文字列を代入 ov_message := lv_ret_message; END GET_MESSAGE;
そんでもってspecを実行!
pasta:get_message mahm$ spec -c -fs get_message_spec.rb トークンを指定せずにメッセージを取得するとき - (1) SELECT message FROM Messages WHERE message_code = 'MES000000'で「正常終了しました。」というメッセージを取得できる - (2) 「MES000000」を指定すると「正常終了しました。」というメッセージを取得 Finished in 0.077543 seconds 2 examples, 0 failures
おおー、通ってる。って、そりゃそうだろ。。
ソースコードのせいでエントリが長くなってきたので、続きは次のエントリで。今度はエラーハンドリングでも実装してみますか。