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

sbtでプロジェクトを分割する

Scala

Scalaで開発してるプロジェクトでsbt0.10を使ってるんですが、テストの数が増えてきて、テストのコンパイルでOut Of Memoryが発生しちゃう、という問題にぶつかりました。
テストケースはScalaTest使ってます。

解決策として、プロジェクトを分割してテストコードを分散させました。

※追記
xuweiさんからのコメントにある通り https://github.com/harrah/xsbt/wiki/Setup-Notes にあるメモリに関する起動オプションをつけることで、開発時は大丈夫でした。
起動オプションで回避できることが多いと思いますので、そちらを先に確認するのが良いです。
開発時は大丈夫だったんですが、jenkinsに新規ジョブを作ったときに発生してしまいました。
subversionリポジトリからチェックアウト→sbt test の流れで全部のテストケースをコンパイルするためだと思います。
テストケースがエンドツーエンドテストということもあって別プロジェクトにして解決しました。



プロジェクト分割の際にやることは以下の通り。

1.サブプロジェクトのディレクトリを作成する(今回は、specs/aaaとspecs/bbbを作成)。
2.projectディレクトリ配下にBuild.scalaを作成する。

object MyBuild extends Build {

  /** 全てのプロジェクトでの共通の定義 */
  val buildOrganization = "my"
  val buildVersion      = "1.0-SNAPSHOT"
  val buildScalaVersion = "2.9.1"

  val buildSettings = Defaults.defaultSettings ++ Seq (
    organization := buildOrganization,
    version      := buildVersion,
    scalaVersion := buildScalaVersion
    // いろいろな設定
  )

  /** ルートプロジェクト */
  lazy val root =
    Project(id = "my-root",
            base = file("."),
            settings = buildSettings)

  /** 以下からサブプロジェクト */
  lazy val aaaSpec =
    Project(id = "specs-aaa",
            base = file("specs/aaa"),
            settings = buildSettings
           ) dependsOn(root % "test->test;test->compile;compile->compile")

  lazy val bbbSpec =
    Project(id = "specs-bbb",
            base = file("specs/bbb"),
            settings = buildSettings
           ) dependsOn(root % "test->test;test->compile;compile->compile")

  //・・・他のサブプロジェクトの定義

}

build.sbtの設定は、各プロジェクトで共有できないので、共通の設定はBuild.scalaに記述する必要がある。
dependsOnで指定しているのは、クラスパスの依存関係を指定している。
上の設定だと、spec-aaaプロジェクトとspec-bbbプロジェクトにおいてtestコマンドを実行した場合、ルートプロジェクトのtestコマンド実行時とcompileコマンド実行時のクラスパスを含めるようになる。

3.各プロジェクトのディレクトリに、src/test/scala ディレクトリを作成する。
4.上で作成したディレクトリにSpecクラスを分散して配置する。
5.各プロジェクトのディレクトリに、build.sbtを作成する(各プロジェクトで個別に設定したい内容を記述する)。

これで完了です!
間違ってたら教えてください!

あっ、sbtのprojectsコマンドでプロジェクトの一覧を表示、projectコマンドでプロジェクト間を移動できます。