My Brain is Open.

思いついたことを適当に列列と

Scala+Javaプロジェクト事始め with sbt (1)

Scalaでコードを書きつつ、Javaコードも書いて、テストも両方書いて、同じプロジェクトとしてビルドしたい!という要望により、環境作成をシコシコとやってみることにしてみました。
今回はScala単体テスト環境構築まで。

とりあえず、sbtが一番簡単そうなのでsbtの利用を前提にしています。あと、環境はMac OS X 10.6.8 + Homebrewです。
*1

sbtインストールとテンプレート生成

便利なテンプレート Typesafe Stack(http://typesafe.com/stack/download) を参考に、Scala環境のセットアップを行います。

Homebrewはインストールもお手軽。

$ brew install scala sbt maven giter8

終わったら、おもむろにプロジェクトを置くディレクトリを作成し、その下で giter8 のコマンドを実行。今回は Akka Actor を使うものを作ってみます。

$ mkdir -p ~/Projects
$ cd ~/Projects
$ g8 typesafehub/akka-scala-sbt

そうすると、githubリポジトリからこのテンプレートを取得し、以下の内容を聞かれるので入力します。

organization [org.example]: <組織名 = rootパッケージ名>
name [Akka Project In Scala]: <プロジェクト名>
akka_version [2.0.1]: (何も記入せずEnter)
version [0.1-SNAPSHOT]: (何も記入せずEnter)

今回は organization = hoge, name = hoge としておきます。

Scalaコードのコンパイル

まずはこのままコンパイルを実行してみます。

$ cd hoge/
$ sbt compile

sbtは複数のScalaバージョンなどにも対応するため内部でScala本体などもキャッシュします。
そのため、scalaコマンドはHomebrewでインストールしたのですが、再度Scalaの本体がインストールされます。
しばらくかかると思いますので、のんびり待ちましょう。*2

もしかしたらこんなOutOfMemoryErrorが出てしまうかも知れませんが、どうもsbtの初回起動に大量のメモリを消費してしまうらしく、アプリの実行が失敗するみたいです。

[error] (run-main) java.lang.OutOfMemoryError: PermGen space

その場合も慌てず、もう一度 sbt run を実行してください。

[info] Running hoge.Hoge 
Count is 3
[success] Total time: 1 s, completed 2012/06/18 18:47:57

これでビルドと実行は成功です。

Scalaコードのテスト

テストを追加します。ScalaコードのテストにはScalaTestを使うことにします。
以下の依存関係を project/HogeBuild.scala に追記します。

-      libraryDependencies += "com.typesafe.akka" % "akka-actor" % "2.0.1"
+      libraryDependencies ++= Seq(
+        "com.typesafe.akka" % "akka-actor"      % "2.0.1",
+        "com.typesafe.akka" % "akka-testkit"    % "2.0.1" % "test" ,
+        "junit"             % "junit"           % "4.10"  % "test" ,
+        "org.scalatest"     %% "scalatest"      % "1.8"   % "test"
+      )

project以下を編集した後は、sbtもリロード。

$ sbt reload

テストコードのサンプルを作ります。ディレクトリを作成して、ファイル編集開始。

$ mkdir -p src/test/scala/hoge/
$ emacs src/test/scala/hoge/HogeTest.scala

Akkaライブラリのより詳細なテストのサンプルは typesafehub/akka-first-tutorial-scalaのテストとかを参照してもらうとして、全然関係ないこんなテストを書いてみます。

package hoge

import org.scalatest.matchers.MustMatchers
import org.scalatest.WordSpec
import org.junit.runner.RunWith

@org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner])
class HogeTest extends WordSpec with MustMatchers {
  "Hoge" must {
    "can treat String.equals" in {
      "test" must equal("test")
    }
  }
}

equals(Javaの等価性検証メソッド)ではないのは注意です。テスト内容は適当すぎますが、まずはこれで実行してみましょう。

$ sbt test
...(足りないライブラリのダウンロードとテスト実行)...
[info] HogeTest:
[info] Hoge 
[info] - must can treat String.equals
[info] Passed: : Total 1, Failed 0, Errors 0, Passed 1, Skipped 0
[success] Total time: 11 s, completed 2012/06/18 19:15:18

まずはこれでテスト完了です。

*1:sbt(Simple-Build-Tool) はScalaで記述できるビルドツールです。依存関係もIvyで解決できます。

*2:他のプロジェクトでダウンロード済みならすぐ終わります。