snippetをspecする

Lift snippetでリクエストパラメータを扱うときのテストケースの作り方。ここではSpecsとMockitoを使って、Servletコンテキストをエミュレートします。

一次情報

[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レスポンスのテスト方法なども気がついたことあったら書き足していくこと>オレ


コメント

コメントしてください
お名前:
入力しなければ「匿名さん」。20字以内。

メール:
入力しても表示しません

URL:
入力すればリンクが貼れます


コメント: