ビヘイビア駆動とかよく分からないけど、とりあえずRSpec書きながらプロシージャを作ってみる #3 まとめ
正直なところ、今までノープランで書いてきたスペックファイルはあまりにあんまりなので、前回の最後に記述した通り、ここらで一回整理してみようと思います。
describeに記述したシチュエーションの振る舞いをitで確かめるのだとすれば、describeの分割単位はパラメータの入力パターン毎であり、itはそのときの振る舞いを一つ一つ定義するのが自然です。例えば「Dogクラスのインスタンスをnewしたとき」というdescribeを描いたならば、itはそのインスタンスの状態を一つ一つ確かめるものであるべきです。
このような前提でスペックファイルを書き直してみると、そこそこスッキリします。
describe "MES000000を指定し、トークンに何も入力しないとき" do it "「正常終了しました。」というメッセージを返す" do end it "ov_retcodeは0(正常終了)である" do end end describe "MES_ERROR_TESTを指定し、トークンに何も入力しないとき" do it "「GET_MESSAGE ERROR:存在しないエラーコードが指定されました。」というメッセージを返す" do end it "ov_retcodeは1(異常終了)である" do end end describe "MES000001を指定し、トークン1に「もっこす」と入力したとき" do it "「私の名前は もっこす です。」というメッセージを返す" do end it "ov_retcodeは0(正常終了)である" do end end
上記のスペックを実行した結果は以下のようになります。
MES000000を指定し、トークンに何も入力しないとき - 「正常終了しました。」というメッセージを返す - ov_retcodeは0(正常終了)である MES_ERROR_TESTを指定し、トークンに何も入力しないとき - 「GET_MESSAGE ERROR:存在しないエラーコードが指定されました。」というメッセージを返す - ov_retcodeは1(異常終了)である MES000001を指定し、トークン1に「もっこす」と入力したとき - 「私の名前は もっこす です。」というメッセージを返す - ov_retcodeは0(正常終了)である
ちなみに、今までの実行結果は以下の通りです。
トークンを指定せずにメッセージを取得するとき - (1) SELECT message FROM Messages WHERE message_code = 'MES000000'で「正常終了しました。」というメッセージを取得できる - (2) 「MES000000」を指定すると「正常終了しました。」というメッセージを取得 - (3) 存在しないmessage_codeを指定するとエラーメッセージとエラーコードが返る トークンを1つ指定してメッセージを取得するとき - (1)「MES000001」でトークン1に「もっこす」と指定すると「私の名前は もっこす です。」と返る Finished in 1.247753 seconds 4 examples, 0 failures
今まで書いてきたスペックがどうにもスッキリしないのは、itにまとめていろんなことを書いていたからなのでした。itで確かめる内容は1つに限定すれば綺麗にまとまります。(theyではないしねえ。。)
実際に実装してみると以下のようになります。
# # get_message_ref1_spec.rb # describeに引数のパターンを記述し、その振る舞いを # itに書いていくやり方 # 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 # ov_retcode OUT VARCHAR2); # target_plsql = <<-PLSQL BEGIN get_message(:iv_message_code, :iv_token1, :iv_token2, :iv_token3, :iv_token4, :iv_token5, :ov_message, :ov_retcode); END; PLSQL # describe "GET_MESSAGEプロシージャで" do before(:all) do # Oracle databaseへ接続 @conn = OCI8.new('apxe','apxe','xe') end after(:all) do # databaseへの接続を切断 @conn.logoff end describe "MES000000を指定し、トークンに何も入力しないとき" do before(:all) 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.bind_param(':ov_retcode', nil, String, 10) @cursor.exec end it "「正常終了しました。」というメッセージを返す" do @cursor[':ov_message'].should == "正常終了しました。" end it "ov_retcodeは0(正常終了)である" do @cursor[':ov_retcode'].should == "0" end end describe "MES_ERROR_TESTを指定し、トークンに何も入力しないとき" do before(:all) do @cursor = @conn.parse(target_plsql) @cursor.bind_param(':iv_message_code', 'MES_ERROR_TEST') @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.bind_param(':ov_retcode', nil, String, 10) @cursor.exec end it "「GET_MESSAGE ERROR:存在しないエラーコードが指定されました。」というメッセージを返す" do @cursor[':ov_message'].should == "GET_MESSAGE ERROR:存在しないエラーコードが指定されました。" end it "ov_retcodeは1(異常終了)である" do @cursor[':ov_retcode'].should == "1" end end describe "MES000001を指定し、トークン1に「もっこす」と入力したとき" do before(:all) do @cursor = @conn.parse(target_plsql) @cursor.bind_param(':iv_message_code', 'MES000001') @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.bind_param(':ov_retcode', nil, String, 10) @cursor.exec end it "「私の名前は もっこす です。」というメッセージを返す" do @cursor[':ov_message'].should == "私の名前は もっこす です。" end it "ov_retcodeは0(正常終了)である" do @cursor[':ov_retcode'].should == "0" end end end
実行結果は以下の通り。
pasta:get_message mahm$ spec -c -fs get_message_ref1_spec.rb GET_MESSAGEプロシージャで MES000000を指定し、トークンに何も入力しないとき - 「正常終了しました。」というメッセージを返す - ov_retcodeは0(正常終了)である GET_MESSAGEプロシージャで MES_ERROR_TESTを指定し、トークンに何も入力しないとき - 「GET_MESSAGE ERROR:存在しないエラーコードが指定されました。」というメッセージを返す - ov_retcodeは1(異常終了)である GET_MESSAGEプロシージャで MES000001を指定し、トークン1に「もっこす」と入力したとき - 「私の名前は もっこす です。」というメッセージを返す - ov_retcodeは0(正常終了)である Finished in 0.213314 seconds 6 examples, 0 failures
逐次的にスペックを増やしていくよりも、最初に日本語のレベルでスペックをある程度書いてから開発するのが吉ですね。スペックを実行したときに、実際の仕様書のように日本語(もしくは英語)が繋がっていると良い感じです。
仕様をコードで書いていくようなイメージなんですね。。って、だからビヘイビア駆動なのか。