02.TestNG と ScalaTest の始め方

もし、TestNG のテストを Scala で記述し実行したいなら、ScalaTest の アサーションとマッチャーを使って、もっと簡潔なコードを書くことができるでしょう。

アサーションを使うには、org.scalatest.Assertions をテストクラスにミックスインします。

import org.scalatest.Assertions

import scala.collection.mutable.ListBuffer

import org.testng.Assert._

import org.testng.annotations.Test

import org.testng.annotations.Configuration

class ExampleSuite extends Assertions {

var sb: StringBuilder = _

var lb: ListBuffer[String] = _

@Configuration { val beforeTestMethod = true }

def initialize() {

sb = new StringBuilder("ScalaTest は")

lb = new ListBuffer[String]

}

@Test def verifyEasy() { // TestNG-スタイルのアサーションを使う

sb.append("かんたん!")

assertEquals("ScalaTest はかんたん!", sb.toString)

assertTrue(lb.isEmpty)

lb += "sweet"

try {

"verbose".charAt(-1)

fail()

}

catch {

case e: StringIndexOutOfBoundsException => // こうなるはず

}

}

@Test def verifyFun() { // ScalaTest のアサーションを使う

sb.append("たのしい!")

assert(sb.toString === "ScalaTest はたのしい!")

assert(lb.isEmpty)

lb += "sweeter"

intercept[StringIndexOutOfBoundsException] {

"concise".charAt(-1)

}

}

}

verifyEasy で使用される TestNG のアサーションと、verifyFun で使用される ScalaTest アサーションの簡潔さの違いが見てとれます。

Scala コンパイラでこのクラスをコンパイルすると、TestNG は作成されたクラスファイルを適切に実行します。

コンパイルするには、以下のように入力します。

scalac -cp scalatest-1.5.jar:testng-5.7-jdk15.jar ExampleSuite.scala

TestNG を使ってテストを実行するには、いくつか方法がありますが、たとえば以下のように入力します。

$ scala -cp .:scalatest-1.5.jar:testng-5.7-jdk15.jar org.testng.TestNG -testclass ExampleSuite

[Parser] Running:

Command line suite

===============================================

Command line suite

Total tests run: 2, Failures: 0, Skips: 0

===============================================

もし、TestNG でテストを実行するか、ScalaTest で実行するかを選択したいなら、org.scalatest.testng.TestNGSuite をミックスインするといいでしょう。

トレイト TestNGSuite は既に Assertions をミックスインしているので、このトレイトは必要ありません。

import org.scalatest.testng.TestNGSuite

import scala.collection.mutable.ListBuffer

import org.testng.Assert._

import org.testng.annotations.Test

import org.testng.annotations.Configuration

class ExampleSuite extends TestNGSuite {

var sb: StringBuilder = _

var lb: ListBuffer[String] = _

@Configuration { val beforeTestMethod = true }

def initialize() {

sb = new StringBuilder("ScalaTest は")

lb = new ListBuffer[String]

}

@Test def verifyEasy() { // TestNG-スタイルのアサーションを使う

sb.append("かんたん!")

assertEquals("ScalaTest はかんたん!", sb.toString)

assertTrue(lb.isEmpty)

lb += "sweet"

try {

"verbose".charAt(-1)

fail()

}

catch {

case e: StringIndexOutOfBoundsException => // こうなるはず

}

}

@Test def verifyFun() { // ScalaTest のアサーションを使う

sb.append("たのしい!")

assert(sb.toString === "ScalaTest はたのしい!")

assert(lb.isEmpty)

lb += "sweeter"

intercept[StringIndexOutOfBoundsException] {

"concise".charAt(-1)

}

}

}

ExampleSuite は有効な TestNG のテストクラスなので、TestNG から実行できます。

$ scala -cp .:scalatest-1.5.jar:testng-5.7-jdk15.jar org.testng.TestNG -testclass ExampleSuite

[Parser] Running:

Command line suite

===============================================

Command line suite

Total tests run: 2, Failures: 0, Skips: 0

===============================================

しかし、ExampleSuite は ScalaTest の Suite でもあるので、ScalaTest からも実行できます。

$ scala -cp scalatest-1.5.jar:testng-5.7-jdk15.jar org.scalatest.tools.Runner -p . -o -s ExampleSuite

Run starting. Expected test count is: 2

ExampleSuite:

[Parser] Running:

Command line suite

- verifyEasy

- verifyFun

===============================================

Command line suite

Total tests run: 2, Failures: 0, Skips: 0

===============================================

Run completed in 315 milliseconds.

Total number of tests run: 2

Suites: completed 2, aborted 0

Tests: succeeded 2, failed 0, ignored 0, pending 0

All tests passed.

最後に、ScalaTest のマッチャーDSL を紹介します。

単純に ShouldMatchersForJUnit をミックスインしてください("should" より "must" の方が好き、という場合は MustMatchersForJUnit をミックスインしてください)。

import org.scalatest.testng.TestNGSuite

import org.scalatest.matchers.ShouldMatchers

import scala.collection.mutable.ListBuffer

import org.testng.Assert._

import org.testng.annotations.Test

import org.testng.annotations.Configuration

class ExampleSuite extends TestNGSuite with ShouldMatchers {

var sb: StringBuilder = _

var lb: ListBuffer[String] = _

@Configuration { val beforeTestMethod = true }

def initialize() {

sb = new StringBuilder("ScalaTest は")

lb = new ListBuffer[String]

}

@Test def verifyEasy() { // ScalaTest のアサーションを使う

sb.append("かんたん!")

assert(sb.toString === "ScalaTest はかんたん!")

assert(lb.isEmpty)

lb += "sweet"

intercept[StringIndexOutOfBoundsException] {

"concise".charAt(-1)

}

}

@Test def verifyFun() { // ScalaTest のマッチャーを使う

sb.append("たのしい!")

sb.toString should be ("ScalaTest はたのしい!")

lb should be ('empty)

lb += "sweet"

evaluating { "concise".charAt(-1) } should produce [StringIndexOutOfBoundsException]

}

}

前の例と同じく、このケースも TestNG 、ScalaTest 双方からテストを実行できます。

$ scala -cp .:scalatest-1.5.jar:testng-5.7-jdk15.jar org.testng.TestNG -testclass ExampleSuite

[Parser] Running:

Command line suite

===============================================

Command line suite

Total tests run: 2, Failures: 0, Skips: 0

===============================================

$ scala -cp scalatest-1.5.jar:testng-5.7-jdk15.jar org.scalatest.tools.Runner -p . -o -s ExampleSuite

Run starting. Expected test count is: 2

ExampleSuite:

[Parser] Running:

Command line suite

- verifyEasy

- verifyFun

===============================================

Command line suite

Total tests run: 2, Failures: 0, Skips: 0

===============================================

Run completed in 315 milliseconds.

Total number of tests run: 2

Suites: completed 2, aborted 0

Tests: succeeded 2, failed 0, ignored 0, pending 0

All tests passed.