CLOVER🍀

That was when it all began.

sbtのテスト関連のメモ

先ほど書いた、こちらのsbt版。

Mavenで、「mvn test」等々とオプションのメモ
http://d.hatena.ne.jp/Kazuhira/20140816/1408198453

まあ、目線はちょっとMavenと違うところもありますが。

とりあえず、対象のプロジェクトでsbtは起動しているものとします。また、使用しているsbtは、0.13.5です。

テストを実行する

普通に。

> test

テストのスキップ

そういえば、sbtって「package」してもテスト実行しないですね。

テストコードを含めてコンパイルする

ソースコードのコンパイルは

> compile

ですが、これだとテストコードはコンパイルしてくれません。

テストコードを含めてコンパイルするには、

> test:compile

となります。

テスト対象のクラスを指定する

Mavenの時と同様、スケープゴート的にこんなクラスを用意。
*中身が超適当なのも一緒

src/test/scala/SampleSpec.scala

import org.scalatest.FunSpec
import org.scalatest.Matchers._

class Sample1Spec extends FunSpec {
  describe("spec") {
    it("test1") {
      val str = "Hello World"

      str should be ("Hello World")
    }

    it("test2") {
      val result = 1 + 2

      result should be (3)
    }
  }
}

class Sample2Spec extends FunSpec {
  describe("spec") {
    it("test1") {
      val str = "Hello World"

      str should be ("Hello World")
    }

    it("test2") {
      val result = 1 + 2

      result should be (3)
    }
  }
}

src/test/scala/ASpec.scala

import org.scalatest.FunSpec
import org.scalatest.Matchers._

class A1Spec extends FunSpec {
  // 中身はSampleXSpecと一緒なので省略
}

class A2Spec extends FunSpec {
  // 中身はSampleXSpecと一緒なので省略
}

src/test/scala/BSpec.scala

import org.scalatest.FunSpec
import org.scalatest.Matchers._

class BSpec extends FunSpec {
  // 中身はSampleXSpecと一緒なので省略
}

テスト対象を絞り込むには、「testOnly」を使用します。

> testOnly Sample1Spec

結果。

[info] Sample1Spec:
[info] spec
[info] - test1
[info] - test2
[info] Run completed in 713 milliseconds.
[info] Total number of tests run: 2
[info] Suites: completed 1, aborted 0
[info] Tests: succeeded 2, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.

ワイルドカードの使用。

> testOnly Sample*Spec

結果。

[info] Sample2Spec:
[info] spec
[info] - test1
[info] - test2
[info] Sample1Spec:
[info] spec
[info] - test1
[info] - test2
[info] Run completed in 436 milliseconds.
[info] Total number of tests run: 4
[info] Suites: completed 2, aborted 0
[info] Tests: succeeded 4, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.

複数指定する場合は、スペース区切りで。

> testOnly Sample*Spec A*Spec

結果。

[info] Sample1Spec:
[info] spec
[info] - test1
[info] - test2
[info] Sample2Spec:
[info] spec
[info] - test1
[info] - test2
[info] A1Spec:
[info] spec
[info] - test1
[info] - test2
[info] A2Spec:
[info] spec
[info] - test1
[info] - test2
[info] Run completed in 2 seconds, 275 milliseconds.
[info] Total number of tests run: 8
[info] Suites: completed 4, aborted 0
[info] Tests: succeeded 8, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.

失敗したテストや前回実行していないテストなどを対象にする

正確には、テストを実装しているクラスですが。これには「testQuick」を使用します。

> testQuick

例えば、失敗するようなテストクラスを2つ作り出してテストして

> test

こういう結果を見ます。

[info] Sample1Spec:
[info] spec
[info] - test1
[info] - test2
[info] Sample2Spec:
[info] spec
[info] - test1
[info] - test2
[info] A1Spec:
[info] spec
[info] - test1
[info] - test2
[info] BSpec:
[info] spec
[info] - test1
[info] - test2 *** FAILED ***
[info]   3 was not equal to 2 (BSpec.scala:15)
[info] A2Spec:
[info] spec
[info] - test1
[info] - test2 *** FAILED ***
[info]   3 was not equal to 2 (ASpec.scala:31)

この後、「testQuick」すると失敗したテストクラスが再度実行されます。

> testQuick

こんな風に。

[info] BSpec:
[info] spec
[info] - test1
[info] - test2 *** FAILED ***
[info]   3 was not equal to 2 (BSpec.scala:15)
[info] A2Spec:
[info] spec
[info] - test1
[info] - test2 *** FAILED ***
[info]   3 was not equal to 2 (ASpec.scala:31)

まあ、ここでは修正してないからまた失敗してますが…。

「testOnly」と同じように、対象のクラスをワイルドカードやスペース区切りで複数指定含めて、指定することができます。

> testQuick A*Spec BSpec

この場合、マッチしたクラスの中に前回成功しているものが含まれている場合は、除外されますが。

また、「testQuick」では、前回のテストで実行していないものや、変更があったりした場合は、そちらも含むようになります。
*例えば、テストメソッドの追加やテストクラスの修正など

前回テストに失敗したものがなかったりした場合は、「testQuick」ではテストは実行されません。
こんな感じになります。

> testQuick
[info] Run completed in 27 milliseconds.
[info] Total number of tests run: 0
[info] Suites: completed 0, aborted 0
[info] Tests: succeeded 0, failed 0, canceled 0, ignored 0, pending 0
[info] No tests were executed.
[info] No tests to run for test:testQuick

テスト対象をフィルタリングする

build.sbtで、以下のような設定を書いて調整するそうな。

testOptions in Test := Seq(Tests.Filter(s => s.endsWith("Test")))

この場合は、クラス名が「Test」で終わっているものを対象にするようで。

テストをfork(別JavaVM)して実行する

build.sbtに、以下の記述を加えます。

fork in Test := true

テストを並列実行しないようにする

sbtはデフォルトでテストを含めたタスクを並列実行するらしいのですが、テストを並列実行しないようにするには、以下の記述をbuild.sbtに加えます。

parallelExecution in Test := false

forkとテストの並列実行の無効化は、クラスタ関係のテストをする時に並列起動したNodeが不用意にクラスタに参加してしまったり、JMXの都合などで設定することが個人的には多いです。

とりあえず、こんなところで。

参考)
Testing(Version 0.13.5)
http://www.scala-sbt.org/0.13.5/docs/Detailed-Topics/Testing.html