┏━━━━━━━━━━━━━━━━━━━━━━━━━━■
┃ ■┃
●┃● ● オ ブ ジ ェ ク ト 倶 楽 部 ■ ┃
┃ ■ ┃
┗━━━━━━━━━━━━━━━━━━━━━━■━━━┛
No.207 2007/10/24
■ I N D E X
┃
┣【Topics】秋イベント「秋の宴」についてお知らせ
┣【プログラミング】Rubyで進むオブジェクトの道 [25]
┣【プログラミング】ゆるーいHaskell [14]
┗【アンケート】気になるシステム業界 ホントのところ
〇━━━━━━━━━━━━━━━━━━━━━━━━━━━T o p i c s━
〇 秋イベント「秋の宴」についてお知らせ
〇 〇━━━━━━━━━━━━━ ━━・
あっという間に満席となってしまった秋イベント。多数のお申し込みをいただ
き、とても嬉しいです。ありがとうございました。
「秋の宴」はPFP関東の皆さんのご協力のもと、懇親会を企画中です。
ご参加予定の皆様は、当日実費3000円をお支払いください。
ご連絡が事後になり申し訳ありません。よろしくお願いいたします。
●「秋の宴」
PFP(プロジェクトファシリテーションを推進する会)さんのご協力のもと、秋の
宴を開催いたします。
参加費 : 3,000円
【PFP関東】 http://projectfacilitationproject.go2.jp/wiki/
※「秋の宴」にご案内してございます。
宴に関する情報は、今後も更新される可能性があります。開催直前までwiki
をご確認ください。
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━1 s t ■━
■
┗【プログラミング】Rubyで進むオブジェクトの道 [25]
■はじめに
今日は、RSpecでスタブの書き方を勉強します。
早速、ソースから
時間が9時なら"hello!"、18時なら "good by!"、それ以外の時間なら"hey!"を
返すプログラムです。
■ geeting.rb
class Greeting
def say
return "hello!" if Time.now.hour == 9
return "good bye!" if Time.now.hour == 18
"hay!"
end
end
ここで厄介なのがTime.nowです。実際のTime.nowのままでは、時間帯によって
返す値が異なり、sayメソッドのテストがやりにくくなっています。
■RSpecのスタブを使わなかった場合
テストし易い構造に変えてしまって対処する方法は、いくつか思いつきます。
方法1
- 厄介な箇所(時間の問い合わせ)をインタフェースで切り出す
- インターフェスに対して時間を問い合わせるように修正
- テストの際は、決まった時間返すスタブを用意し、Greetingオブジェクトに
インジェクトしてテストする。
方法2
-厄介な時間の問い合わせの箇所をメソッド化する
-テストの際は時間の問い合わせの箇所をオーバライドして決まった時間を返
すようにする。
方法3
-そもそもAPIが悪いと判断。sayメソッドの引数に時間を明示的に渡すように
APIを変えてしまう。
■RSpecのスタブを使った場合
RSpecのstub!メソッドを使えば、上記のような対処は不要で、上記のソースの
ままでもスタブによるテストが可能です。下記にRSpecを使ったスタブによるテ
ストを例を示します。
-- geeting_spec.rb
describe Greeting, "at 9:00" do
before(:each) do
Time.stub!(:now).and_return(Time.gm(*"2007-10-01-09-00".split("-")))
@greeting = Greeting.new
end
it "should say 'hello!'" do
@greeting.say.should == "hello!"
end
end
describe Greeting, "at 18:00" do
before(:each) do
Time.stub!(:now).and_return(Time.gm(*"2007-10-01-18-00".split("-")))
@greeting = Greeting.new
end
it "should say 'good bye!'" do
@greeting.say.should == "good bye!"
end
end
describe Greeting, "not 9:00 or 18:00" do
(0..23).reject { |hour| hour == 9 or hour == 18 }.each { |hour|
it "should say 'hay!'" do
Time.stub!(:now).and_return(Time.gm(*"2007-10-01-#{hour}-00".split("-")))
@greeting = Greeting.new
@greeting.say.should == "hay!"
end
}
end
■解説
Time.stub!(:now).and_return(Time.gm(*"2007-10-01-09-00".split("-")))
がポイントです。これだけで、実際の時間ではなくスタブによって指定された
時間(9時)を返すようになります。
■補足:スタブとモックの違い
xUnit Test Patterns[*1]によると、スタブとモックの定義を分けています。
簡単に違いを説明するとスタブは、単に決まった値をテスト対象の要素に返す
だけで(indirect input)、期待した振る舞いを行ったかのVerifyは、テスト対
象の要素に問い合わせます。
#上記の例では
テスト対象要素:@greeting
スタブ : Time.stub!(:now).and_return(Time.gm(*"2007-10-01-#{hour}-00".split("-")))
Verifyかの問い合わせ : @greeting.say.should == "hello!"
に相当します。
対して、モックは、テスト対象の要素とモックとの間でどんなメッセージのや
り取り行うかの期待をモックに明記し、テスト対象の要素を実行したのちに、
モックにVerifyかを問い合わせます。
次回は、RSpecを使ったモックについて勉強してみたいと思います。(IENAGA)
■参考
[1] : xUnit Test Patterns
http://xunitpatterns.com/Test%20Double.html
http://xunitpatterns.com/Test%20Stub.html
http://xunitpatterns.com/Mock%20Object.html
_______________________________________________________________________
この記事への評価にご協力をお願いします。
URLをクリックして、「ご協力ありがとうございました」のメッセージがご使用
のブラウザに表示されれば投票完了です。
良かった:
http://www.ObjectClub.jp/community/object_ml/estimate?vol=E006-24&choice=0
普通:
http://www.ObjectClub.jp/community/object_ml/estimate?vol=E006-24&choice=1
イマイチ:
http://www.ObjectClub.jp/community/object_ml/estimate?vol=E006-24&choice=2
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━2 n d ■━
■
┗【プログラミング】ゆるーいHaskell [14]
こんにちは。西川です。
今回はリストモナドについてお話しします。これまで普通に使ってきたあのリ
ストもHaskellではモナドの仲間です。リストの定義をよく見てみましょう。
ghciを起動します。
> > :i []
data [] a = [] | a : [a] -- <wired into compiler>
instance (Eq a) => Eq [a] -- Defined in GHC.Base
instance Monad [] -- Defined in GHC.Base
(リストのinstance宣言がつづきます)
リストがモナドになっていることがお分かりになると思います。リストはモナ
ドクラスのインスタンスなのです。
# リストのモナドクラスのinstance宣言
instance Monad [] where
m >>= k = foldr ((++) . k) [] m
m >> k = foldr ((++) . (\ _ -> k)) [] m
return x = [x]
fail _ = []
リストのinstance宣言は上記のようになっています。
実際にリストをモナドとして操作してみましょう。
Prelude> [1,2,3] >>= return . (1+)
[2,3,4]
いきなりすぎてよく分かりませんね。上記のinstance宣言からこの操作は以下
の操作と等価です。
0> foldr ((++) . (return . (1+))) [] [1,2,3]
((++) . (return . (1+))の見通しが悪いので、ラムダ式を使って見やすい形に
変形してみましょう。return x
= [x]で、関数合成を無くしてみると、
1> foldr (\x -> ([1+x]++)) [] [1,2,3]
と変形することができます。これをfoldrの定義からこれを展開すると、
2> [1+1] ++ (foldr (\x -> ([1+x]++)) [] [2,3])
3> [1+1] ++ ([1+2] ++ (foldr (\x -> ([1+x]++)) [] [3]))
4> [1+1] ++ ([1+2] ++ ([1+3] ++ (foldr (\x -> ([1+x]++)) [] [])))
5> [1+1] ++ ([1+2] ++ ([1+3] ++ ([])))
6> [2,3,4]
となります。まあなんとなくリストはモナドなんだな、ということが分かって
いただければ大丈夫です。
最後にguard関数を紹介しましょう。guard関数を使って整数のリストから奇数
のみ抽出する関数を作ります。
> > let oddList xs = xs >>= \x -> guard (odd x) >> return x
# let oddList xs = do x <- xs; guard (odd x); return xとも書くことがで
きます。
> > oddList [1..10]
[1,3,5,7,9]
guard関数についてちょっと見てみましょう。
guard :: (MonadPlus m) => Bool -> m ()
guard True = return ()
guard False = mzero
guard関数はControl.Monadモジュールで上記のように定義されている関数です。
guard関数の型に注目です。
「Control.Monad.guard :: (Control.Monad.MonadPlus m) => Bool -> m ()」の
「(Control.Monad.MonadPlusm) =>」の部分は『以降に出現する型変数mという
のはControl.Monad.MonadPlusのクラス(のインスタンス)でなければならない』
という注釈にあたります。
Control.Monad.MonadPlusを見てみましょう。
> > :i Control.Monad.MonadPlus
class (Monad m) => Control.Monad.MonadPlus m where
Control.Monad.mzero :: m a
Control.Monad.mplus :: m a -> m a -> m a
-- Defined in Control.Monad
> > Control.Monad.mzero :: [a]
[]
> > Control.Monad.mplus [1,2,3] [4,5,6]
[1,2,3,4,5,6]
リストモナドでのmzero,mplusの定義をghciから確認してみました。
先程のoddList関数の「guard(odd x)」の「odd x」がFalseのときは空リストが
返ってきます。ちょうどこのような感じになります。
> > [] >> return 1
[]
「odd x」がTrueの場合はこのような感じです。
> > [()] >> return 1
[1]
今ひとつこのoddList関数の振舞いが分かりづらい、という方はリストの(>>=)
関数、(>>)関数、return関数の定義からoddList関数を変形すると見通しが良く
なるかもしれません。今回はリストモナドについてお話しました。(西川)
______________________________________________________________________
この記事への評価にご協力をお願いします。
URLをクリックして、「ご協力ありがとうございました」のメッセージがご使用
のブラウザに表示されれば投票完了です。
良かった:
http://www.ObjectClub.jp/community/object_ml/estimate?vol=E008-13&choice=0
普通:
http://www.ObjectClub.jp/community/object_ml/estimate?vol=E008-13&choice=1
イマイチ:
http://www.ObjectClub.jp/community/object_ml/estimate?vol=E008-13&choice=2
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━3 r d ■━
■
┗【アンケート】気になるシステム業界 ホントのところ
今週は「読者の皆さんの職場はどこですか?」のホントのところ。
オブラブメルマガ編集のひそやかな楽しみは、読者の皆さんからの感想メール。
お返事は遅いですが、それぞれに目を通しつつ、皆さんがどこからこの感想を
送ってくれているのか楽しみにしています。東京から近いところ。遠いところ。
「雪がふりました」「桜が咲きました」など、それぞれの土地の便りを載せて
届くメールは、普段お目にかかれない読者の皆さんとの距離をぐっと近づけて
くれますね。さて、皆さんの職場はどこでしょうか?
北海道。
http://www.ObjectClub.jp/special/kininaru/vote?vol=173&choice=0
東北。
http://www.ObjectClub.jp/special/kininaru/vote?vol=173&choice=1
関東。
http://www.ObjectClub.jp/special/kininaru/vote?vol=173&choice=2
中部(北陸・甲信越・東海)。
http://www.ObjectClub.jp/special/kininaru/vote?vol=173&choice=3
近畿。
http://www.ObjectClub.jp/special/kininaru/vote?vol=173&choice=4
中国。
http://www.ObjectClub.jp/special/kininaru/vote?vol=173&choice=5
四国。
http://www.ObjectClub.jp/special/kininaru/vote?vol=173&choice=6
九州・沖縄。
http://www.ObjectClub.jp/special/kininaru/vote?vol=173&choice=7
国外。
http://www.ObjectClub.jp/special/kininaru/vote?vol=173&choice=8
それは秘密です。
http://www.ObjectClub.jp/special/kininaru/vote?vol=173&choice=9
ちょっと語らせて!
詳細をこのメールに返信ください!!
アンケート結果はオブジェクト倶楽部サイト上にて公開します。お楽しみに。
なお、前号「プロジェクトファシリテーションを何で知りましたか?」の結果
は公開中。ぜひご覧下さい。
⇒http://www.ObjectClub.jp/special/kininaru/vol172/PlonePopoll_results2
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━--■--●--■
■
┗編集後記
こんにちは、編集人です。席替えがありました。急に見通しが良くなっちゃって、
まだなんとなく気持ちが落ち着きません。皆さんの職場は、よく席替えがあり
ますか?席が替わって気がついたのは、オブラブスタッフ職場におけるメンバー
のPF浸透度。気がつけば可動式ホワイトボードがたくさん増えて、圧巻です!
今週の強引な一言
***酒は天の美禄(ことわざ)***
お酒は天から賜った手厚い封禄であるという意味。お酒を飲むときは愚痴は脇
において、天からのご褒美を存分に味わいたいものですね。ゆっくりと。
(上田雅美)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━--■--●--■
● ご意見、ご感想は ⇒このメールに返信ください
〇 配信中止、アドレス変更は ⇒http://www.ObjectClub.jp/community/object_ml/help/
〇 免責事項、過去の記事は ⇒http://www.ObjectClub.jp/community/object_ml/
■ 発行:オブジェクト倶楽部 ⇒http://www.ObjectClub.jp/
■ 編集代表:平鍋 健児
Copyright (c)2003-2007 オブジェクト倶楽部. All Rights Reserved.
powered by Eiwa System Management, Inc.