作者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