作者godfat (godfat 真常)
看板PLT
標題Re: [心得] [Scala] 簡簡單單做 Mock 及 BDD。
時間Sat Jan 16 21:12:59 2010
※ 引述《brianhsu (墳墓)》之銘言:
: 推 godfat:btw, 之前在試 scalacheck, 不過跟 2.8 相容還不完整.. 01/16 16
: → godfat:現在不知道如何了?有一陣子沒注意了 01/16 16
: → brianhsu:用在 2.8 上用的話好像要抓 Snapshot 版,不過我沒試過。 01/16 18
: → brianhsu:http://0rz.tw/h72zm 01/16 18
我說的 scalacheck 是這個:
http://code.google.com/p/scalacheck/
這是模仿 Haskell 的 QuickCheck 做的東西。
他主要的作法是,你提供產生 test data 的 function,
再提供一組恆為真的 function, 他則產生一定數量的隨機測試。
比方說有個隨機 int 產生 function 是 rand,
恆為真的 function 是 x + y = y + x
接著 QuickCheck / ScalaCheck 就會產生比方說 100 組隨機測資,
如果每一個的結果都確實是 True, 則這個 check 就會過。
說著忍不住就去抓來試試了... 依照這東西,
範例中的 WrongXML 的相關測試會寫成這樣:
(以下程式是用 scala 2.8 r20436 和 scalacheck 1.7 snapshot 測的)
object CheckGeo{
// 我們產生測資的 function 是隨便在幾個 XML 裡面挑一個出來:
val gen = Gen.oneOf( <a/>, <b/>, <a><b/></a> )
// 用這方式告訴 ScalaCheck, 隨機的 XML 要用 gen 產生:
implicit def arbitrary_xml: Arbitrary[Elem] = Arbitrary(gen)
def check = forAll{ (xml: Elem) =>
// 產生 WrongXML 的 trait...
trait WrongXML extends LoadXML{
override def loadXML = xml
}
val service = new GeoService ("中央研究院") with WrongXML
// 一個 check 只能檢查一件事...
// 不然要用 && 接起來
service.placemarkList == Nil
}.check
}
最後執行測試:
CheckGeo.check
他會告訴你:
+ OK, passed 100 tests.
這東西要好用,大概得要有足夠好的測資產生 function.
像是 int, random string 這種很好產生。random xml 就麻煩了。
不過有寫好的話,我想可能比 unit test 更穩固一點。
雖然我們可能會陷入一個難題:
「產生測資的 function 真的是正確的嗎?」
我不知道,除了測試以外,我還沒有實際用過這種方式。
另一方面,範例中提到的 Mock, 看起來應該是 Stub.
Martin Fowler 有一篇文章講得很清楚:
http://martinfowler.com/articles/mocksArentStubs.html
簡單地說,所有的 double (替身) 有以下幾種:
0. dummy, 完全沒用到的東西
1. fake, 另一種實作
2. stub, 回傳假的,預先設好的資料
3. mock, 會預測執行順序與方式的東西
例如在這邊如果要 mock loadXML, 可能會像是這樣:
stub_source = (...)
mock(Source).fromURL.with(url, "utf-8").return(stub_source)
表示說等一下 Source 會被呼叫 fromURL 這個 method,
而且會收到 url, "utf-8" 這兩個 argument, 然後請回傳 stub_source.
也就是說,mock 是在做預測 method call 的動作。
也因此才叫 "Behavior" Driven
==
多虧最近 brianhsu 板友的 Scala 文章,又繼續提起對 Scala 的興致了
不過... 今天正事就沒做幾件 囧> 真糟糕|||b
我自己是拿這個在做實驗,有興趣歡迎參觀看看 :D
http://github.com/godfat/spellbook
--
生死去来、棚頭傀儡、一線断時、落落磊磊
《花鏡》-世阿弥
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.135.160.129