連載
» 2013年07月29日 18時00分 公開

Scala+Play 2.0でWebアプリ開発入門(8):Playのグローバルな設定&spec2でBDDなテスト (3/4)

[中村修太,クラスメソッド]

specs2でPlayアプリのテストクラスを作成

 ユーザー登録を実装したので、テストクラスを作成していきましょう。

サービステスト作成

 まずはtestディレクトリ下にUserServiceSpec.scalaファイルを作成し、UserService用のテストを作成します。

import org.specs2.mutable._
import play.api.test._
import play.api.test.Helpers._
import play.api._
import play.api.mvc._
import play.api.db._
import play.api.Play.current
import anorm._
import services.UserService
import org.specs2.specification.{ BeforeExample, AfterExample, Scope }
//1.クラス定義
class UserServieSpec extends Specification with BeforeExample with AfterExample {
  //2.FakeApplication作成
  def fakeApp = FakeApplication(
    additionalConfiguration = Map(
      "db.default.driver" -> "com.mysql.jdbc.Driver",
      "db.default.url" -> "jdbc:mysql://localhost/gyro",
      "db.default.user" -> "<ユーザー名>",
      "db.default.password" -> "<パスワード>",
      "db.default.partitionCount" -> 2,
      "db.default.maxConnectionsPerPartition" -> 5,
      "db.default.minConnectionsPerPartition" -> 5))
  def before = {
    //テスト用ユーザーを登録
    running(fakeApp) {
      DB.withConnection { implicit c =>
        SQL(
          """ insert into User(id,name,email,password) values({id},{name},{email},{password})
              """).on('id -> 1, 'name -> "taro", 'email -> "taro@taro.com", 'password -> "taropass").executeInsert()
      }
    }
  }
  def after = {
    //テーブルのデータを削除
    running(fakeApp) {
      DB.withConnection { implicit c =>
        SQL(""" delete from Post """).executeUpdate()
        SQL(""" delete from User """).executeUpdate()
      }
    }
  }
  //3.テスト定義
  "UserService" should {
    "insert user info" in {
      running(fakeApp) {
        UserService.entry("test", "test@test.com", "testpass") match {
          case Some(id) => print("ok")
          case None => failure("entry failure")
        }
      }
    }
  }
  "UserService" should {
    "get user by id" in {
      running(fakeApp) {
        val user = UserService.findByPk(1)
        user should not be (None)
        user.get.name must equalTo("taro")
      }
    }
  }
}

 テストクラスのポイントを解説していきます。

  • 1.クラス定義

 まずはクラス定義とbefore/afterメソッドについてです。specs2のテストクラスは、Specificationを継承することで定義します。

 UserServieSpecではさらに、BeforeExampleとAfterExampleをミックスインしています。この2つのトレイトはbeforeメソッド、afterメソッドを持っており、これらをオーバーライドすることで、事前処理/事後処理を定義できます。

 UserServieSpecでは事前処理としてテストユーザーの登録、事後処理としてPostとUserテーブルの全データ削除をしています。

class UserServieSpec extends Specification with BeforeExample with AfterExample {
・
・
  def before = {
    //テスト実行前の事前処理
  }
  def after = {
    //テスト実行後の事後処理
  }
・
・
  • 2.FakeApplication作成

 DBやルータのテストなど、起動中のアプリケーションに依存するコードをテストする場合、FakeApplicationオブジェクトを使用して疑似的なアプリを作成します。上記テストクラスでは最初にFakeApplicationを作成しています。

 FakeApplicationには、いろいろな設定値を渡して、設定の追加/上書きができます。UserServieSpecのFakeApplicationでは、DB情報と共に最大接続数の情報も渡しています(※この記述をしないと、テスト実行時に接続エラーが発生する可能性があります)。

  def fakeApp = FakeApplication(
    additionalConfiguration = Map(・・・))
  • 3.テスト定義

 "UserService" should〜から始まる部分がテスト定義部分です。UserServiceSpecでは登録と検索の2つのテストが定義されています。

  "UserService" should {
    "insert user info" in {
      running(fakeApp) {
       ・・・
      }
    }
  }
  "UserService" should {
    "get user by id" in {
      running(fakeApp) {
       ・・・
      }
    }
  }

 テストメソッド内では、runningメソッドへfakeAppを渡してDBをテストできる状態にしています。これを記述しないと、DB接続ができずにエラーが発生するので注意してください。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。