超適当訳写経 『Groovy - Unit Testing』(Groovy公式ドキュメント) #junitbook

『GroovyからJUnitを扱う』ための前練習的な取り組みとして、Groovy公式ドキュメントから関連するページを写経してみよう、というエントリ。まずは更にそれら前段階として『Groovyでのユニットテスト』ページから超適当訳で実践メモを残してみる。超適当訳と自分の実践メモやら感想やら入り混じるので精度としてはかなり不安な気もしますが、その辺御容赦を。m(_ _)m 御指摘・修正等あれば速やかに対応したいと思います。

Groovyの利点

GroovyはJUnitテスティングを幾つかの方法でより、シンプルに、より"Groovy"にします。

この辺も参照。

記述例

Groovyでユニットテストを書く場合、GroovyTestCaseを拡張したクラスを作成する必要がある。

import static org.junit.Assert.*;

class MyTest extends GroovyTestCase {

	void testSomething() {
		assert 1 == 1
		assert 2 + 2 == 4 : "We're in trouble, arithmetic is broken"
	}
}

Groovyのテストアサーション

  • GroovyTestCaseでは以下のテストアサートメソッドを追加で提供している。処理詳細はドキュメント参照。
  • assertArrayEquals
  • assertLength
  • assertContains
  • assertToString
  • assertInspect
  • assertScript
  • shouldFail

詳細

  • デフォルトでGroovyテストケースはJavaバイトコードを吐くのでJavaJUnitコードと同じ(扱い)。
  • 以下Maven周りの事について記載があるがそんなにMaven使いでも無いのでここは割愛。時が来たら読む。

コマンドラインでの実行

  • IDEメインで使うのでここも割愛。時が来たら読む。

IDEでのGroovyTestCaseの実行

Eclipse上でGroovyTestCaseを含むTestSuiteを実行

  • TestSuiteのsuite()メソッドはテストを返す。
  • suite()メソッド内ではGroovyTestSuiteを作成したり、TestSuiteを追加したり出来る。
  • 詳細はコード参照。
  • suiteクラス
package junitbook.sandbox;

import static org.junit.Assert.*;
import junit.framework.TestSuite;

class MyTestSuite extends TestSuite {
	private static final String TEST_ROOT = "test/junitbook/sandbox/"
	public static TestSuite suite() throws Exception {
		TestSuite suite = new TestSuite();
		GroovyTestSuite gsuite = new GroovyTestSuite();
		suite.addTestSuite(StackTest.class)
		suite.addTestSuite(gsuite.compile(TEST_ROOT + "GroovyStackTest.groovy"))
		suite.addTestSuite(gsuite.compile(TEST_ROOT + "MyTest.groovy"))
		return suite;
	}

}
  • Suiteクラスに対する、テストクラス各種。内容は超適当ですのであしからず。
package junitbook.sandbox;

import static org.junit.Assert.*;
import groovy.util.GroovyTestCase;

import org.junit.Test;

public class StackTest extends GroovyTestCase {

	@Test
	public void test() {
		assertEquals(1, 1);
	}

}
    • GroovyStackTest.groovy
package junitbook.sandbox;

import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;

import org.junit.Test;

class GroovyStackTest extends GroovyTestCase {

	@Test
	void testAdd() {
		Stack stack = new Stack();
		assertThat(stack.add(10, 20), is(30))
	}

	@Test
	void testAdd2() {
		Stack stack = new Stack();
		assertThat(stack.add(3, 4), is(7))
	}

}
    • MyTest.groovy
package junitbook.sandbox;

import static org.junit.Assert.*;

class MyTest extends GroovyTestCase {

	void testSomething() {
		assert 1 == 1
		assert 2 + 2 == 4 : "We're in trouble, arithmetic is broken"
	}
}

最初上手く実行出来なくて、パスとかの問題なのかな?と思いきやこういう事でした。GroovyTestSuite使う際はSuite対象となるクラスもGroovyTestCaseなりを拡張させとかないとダメなんですね。分かってみれば確かにそうですけど。

  • クラス実行は繋がるがテストが無い(test not founds)と言われる。@Testで宣言してるんだけどな〜
  • ん、これもしかしてGroovyTestCase拡張しないとだめ?→各クラス、GroovyTestCaseを拡張したら認識してくれた(それまでそこに気付かず延々空振ってた)

ただこれ、Javaのクラスも同じようにするのは何か違う気がする(写経対象のページでは『Java, Groovy混在で行けるぜ』とは書いてあるものの)ので、実際の利用シーンでは

  • JavaのテストクラスはJavaのTestSuiteで取り纏め
  • GroovyのテストクラスはGroovyのTestSuiteで取り纏め

という形を採った方が混乱は少なさそうだな、という感じです。

スクリプトファイルをユニットテストのように利用

こちらも公式ページのコードに倣い、試してみる。

package junitbook.sandbox

import groovy.util.GroovyTestSuite
import junit.framework.Test
import junit.textui.TestRunner
import org.codehaus.groovy.runtime.ScriptTestAdapter

class AllTests {
	static Test suite() {
		def allTests = new GroovyTestSuite();
		def testRoot = "test/junitbook/sandbox/"
		allTests.addTest(new ScriptTestAdapter(allTests.compile(testRoot + "GroovySrciptOne.groovy"), [] as String[]))
		allTests.addTest(new ScriptTestAdapter(allTests.compile(testRoot + "GroovyScriptTwo.groovy"), [] as String[]))
		return allTests
	}
}
TestRunner.run(AllTests.suite())

実行に使ったGroovyスクリプト2つ。例によって中身は超適当。

  • GroovyScriptOne.groovy
package junitbook.sandbox

x = [1,2,3]
assert x.size() == 3
  • GroovyScriptTwo.groovy
package junitbook.sandbox

assert "Hello,Groovy!".length() == 13

これはこれでJava/Groovyクラス同様、使うならSuiteクラスを分けて、という感じになりそうですね。

ページの残りは割愛。