読者です 読者をやめる 読者になる 読者になる

seratch's weblog in Japanese

About Scala, Java and Ruby programming in Japaense. If you need English information, go to http://blog.seratch.net/

Play20 で ScalaTest を使ってテストを書く方法

Scala Play

specs2 以外を使っていいのか?

The default way to test a Play 2 application is by using specs2.

http://www.playframework.org/documentation/2.0/ScalaTest

しかし play-test のソースコードを見る限り、2.0 時点では Helpers などが specs2 の API に依存しているわけではないようです。

Play 開発チームが「 specs2 が default way」と言っている以上、今後 play-test が specs2 でしか動かないものに育っていく可能性がないわけではないですが、2.0 時点ではフレームワーク側に specs2 しか使えないという制限はないようです。

ただ dependency 解決だけだとテスト実行ができなかった

ただ、sbt の settings がデフォルトでは specs2 しか想定していないようで、そのままだと実行エラーになりました。

単に project/Build.scala に ScalaTest の dependency を追加しただけだと、こんな感じのエラーに・・

[error] Could not run test test.ApplicationSpec: java.lang.IllegalArgumentException: Unrecognized argument: sequential
Throwable escaped the test run of 'test.ApplicationSpec': java.lang.IllegalArgumentException: Unrecognized argument: sequential
java.lang.IllegalArgumentException: Unrecognized argument: sequential
	at org.scalatest.tools.ScalaTestFramework$ScalaTestRunner.parsePropsAndTags(ScalaTestFramework.scala:286)
	at org.scalatest.tools.ScalaTestFramework$ScalaTestRunner.run(ScalaTestFramework.scala:137)
	at org.scalatools.testing.Runner2.run(Runner2.java:16)
	at sbt.TestRunner.delegateRun(TestFramework.scala:61)
	at sbt.TestRunner.run(TestFramework.scala:55)
	at sbt.TestRunner.runTest$1(TestFramework.scala:75)
	at sbt.TestRunner.run(TestFramework.scala:84)
	at sbt.TestFramework$$anonfun$6$$anonfun$apply$8$$anonfun$7$$anonfun$apply$9.apply(TestFramework.scala:183)
	at sbt.TestFramework$$anonfun$6$$anonfun$apply$8$$anonfun$7$$anonfun$apply$9.apply(TestFramework.scala:183)

フォーラムに解決方法がありました。

https://groups.google.com/forum/#!msg/play-framework/rZBfNoGtC0M/_jVyRccwEHkJ

project/Build.scala がこのようになっていれば OK です。

import sbt._
import Keys._
import PlayProject._

object ApplicationBuild extends Build {

    val appName         = "play20-example"
    val appVersion      = "1.0-SNAPSHOT"

    val appDependencies = Seq(
      "org.scalatest" %% "scalatest" % "1.7.1" % "test"
    )

    val main = PlayProject(appName, appVersion, appDependencies, mainLang = SCALA).settings(
      testOptions in Test := Nil
    )

}

以下は ScalaTest の FlatSpec で書いてみたサンプルです。

package test

import play.api.test._
import play.api.test.Helpers._

import org.scalatest.FlatSpec
import org.scalatest.matchers.ShouldMatchers

class ApplicationSpec extends FlatSpec with ShouldMatchers {
  "GET /" should "return 200 OK" in {
    running(FakeApplication()) {
      val root = routeAndCall(FakeRequest(GET, "/")).get
      status(root) should equal(OK)
    }
  }
}

実行結果はこんな感じになります。

[play20-example] $ test-only test.ApplicationSpec
[info] ApplicationSpec:
[info] GET / 
[info] - should return 200 OK
[info] Passed: : Total 1, Failed 0, Errors 0, Passed 1, Skipped 0
[success] Total time: 2 s, completed Apr 1, 2012 5:19:25 PM
[play20-example] $