一次情報
[Liftweb wiki]How To: Unit test lift snippets with a logged in user
[Liftweb ML]
[specs wiki]Execute the Example expectations inside a specific context
環境準備
specs1.6.1以上と、モック生成ライブラリMockitoを使ったやり方です。特にspecs1.6.0では動かないのでバージョンに注意。
simple-build-toolの場合の設定方法:
class MyProject(info: ProjectInfo) extends DefaultWebProject(info){
:
val specs = "org.scala-tools.testing" % "specs" % "1.6.1" % "test"
val mockito = "org.mockito" % "mockito-core" % "1.8.1" % "test"
:
}
S.paramをテストするサンプル
例:リクエストパラメータに応じたコンテンツを取得してリンクを生成するSnippet
class ProductLinkTo {
def edit( xhtml:NodeSeq ) = S.param("product_id") match {
case Full(id) =>
Product.find(id.toLong) match {
case Full( p ) => <a href={"/product/edit/"+p.id}>{p.title}を編集</a>
case _ => <span>Not Found</span>
}
case _ => <span>Access Error</span>
}
}
ここで問題になるのは、Webコンテナを動かさないと「S」オブジェクトの操作ができないわけですが、HttpRequestのモックを使ってエミュレートします。
このSnippetのspecsは以下になります。
object ProductLinkToSpec extends Specification with Mockito {
var request = mock[Req] //requestのモックを生成
var session = new LiftSession("", StringHelpers.randomString(20), Empty)
//request/sessionのコンテキスト内でスペックfを実行する。
def inSession(f: =>Any) {
S.init(request, session) { f }
}
//モックRequestへのパラメーターセッター
def setParameter(name: String, value: String){
request.param(name) returns Some(value)
}
new SpecContext{
beforeSpec{ (new bootstrap.liftweb.Boot).boot }
//各スペックをinSession内で実行する。
aroundExpectations(inSession(_))
}
"LinkTo Snippet" should {
"build link" in {
//Productを生成してidをリクエストパラメータへ
var product_id = Product.create.title("商品").saveMe.id.is
setParameter("product_id",product_id.toString)
//snippetはちゃんとリンクを返しているか。
//specs.XMLMatcherなどを参考に
val snippet = new ProductLinkTo
snippet.edit(NodeSeq.Empty) must \\("a")
Product.find(product_id).open_!.delete_!
}
}
}
snippetの入出力はXML型なのでScalaでは扱いやすい(テスト書きやすい)。例えば「生成したリストが何行か」といったテストは一発で書けるでしょう。
snippet.list( node ) \\ "li" length must be 15
とか。specsでもXMLMatcherは標準添付。
LiftのコアアーキテクチャであるSnippetが非常にさくさくテスト駆動開発できる点には結構注目してよいと思う。ここまでViewテストがしやすいフレームワーク&言語は他にナイんじゃないかなと思います。
※パラメータだけでなく、SessionやHTTPレスポンスのテスト方法なども気がついたことあったら書き足していくこと>オレ