新機能と主な変更点¶
0.7¶
スナップショットリポジトリの移動¶
Spockのスナップショットは http://oss.sonatype.org/content/repositories/snapshots/ から取得できるようになりました。
新しいリファレンスドキュメント¶
Spockの新しいリファレンスドキュメントはhttp://docs.spockframework.orgで参照できます。ここにはhttp://wiki.spockframework.orgにあるドキュメントを徐々に移動していきます。このドキュメントは各バージョン毎に公開しています(例えばhttp://docs.spockframework.org/en/spock-0.7-groovy-1.8)。スナップショットの最新ドキュメントはhttp://docs.spockframework.org/en/latestを参照してください。Spock 0.7の時点ではデータ駆動テストと相互作用中心のテストの記述が完了しています。
TooManyInvocationsError
のモッキング失敗メッセージの改善¶
TooManyInvocationsError
発生時の診断メッセージが大幅に改善されました。以下に例を示します。
Too many invocations for:
3 * person.sing(_) (4 invocations)
Matching invocations (ordered by last occurrence):
2 * person.sing("do") <-- this triggered the error
1 * person.sing("re")
1 * person.sing("mi")
TooFewInvocationsError
のモッキング失敗メッセージの改善¶
TooFewInvocationsError
発生時の診断メッセージが大幅に改善されました。以下に例を示します。
Too few invocations for:
1 * person.sing("fa") (0 invocations)
Unmatched invocations (ordered by similarity):
1 * person.sing("re")
1 * person.say("fa")
1 * person2.shout("mi")
スタブ¶
従来のモックオブジェクトに加えて、スタブのサポートを追加しました。
def person = Stub(Person)
スタブはモックオブジェクトの機能制限版で、モックに比べより本物の値に近い値を返します。また、スタブは多重度を定義できない以外は、モックのインタラクションと同じよう見えますが、読み手に対し役割をより明確にできる効果があります。
スパイ¶
従来のモックオブジェクトに加えて、スパイのサポートを追加しました。
def person = Spy(Person, constructorArgs: ["Fred"])
スパイは、この例のPerson
インスタンスのように本物のオブジェクト上に構築されます。インタラクションが一致しないスパイに対するすべての呼び出しは、本物のオブジェクトへと処理が委譲されます。このようにスパイを使用することで、本物のオブジェクトの必要な部分のみ振る舞いを変更し、またその呼び出しを監視することができます。さらに、スパイはパーチャルモックとして使用することも可能です。
モック作成時のインタラクション定義¶
モック作成時にインタラクションを定義できようになりました。
def person = Mock(Person) {
sing() >> "tra-la-la
3 * eat()
}
この機能は、特にStubsで便利な機能です。
Groovyモック¶
Groovyのコードに特化した特別なモックオブジェクトの機能を追加しました。
def mock = GroovyMock(Person)
def stub = GroovyStub(Person)
def spy = GroovySpy(Person)
Groovyモックは、自動的にgroovy.lang.GroovyObject
を実装します。これは静的に定義されたメソッドと同じように、動的なメソッドに対するスタビングとモッキングが可能です。Groovyモックは、GroovyのコードではなくJavaから呼び出されると、通常のモックと同じように振舞います。
グローバルモック¶
Groovyモックはグローバルに作成できます。
GroovySpy(Person, global: true)
このグローバルモックはクラスの型にのみ使用できます。これは、その型の全てのインスタンスを差し替え、スタビングとモッキングはこれらの型全てに影響を与えます(このような動作をするGroovyのMockFor
とStubFor
をご存知かも知れません)。さらにグローバルモックは、その型のコンストラクタ、およびstaticメソッドのモッキングが可能です。
コンディションのグループ化¶
この機能はGroovyのObject.with
からインスパイアされました。これはSpecification.with
メソッドを使用することで、特定の対象オブジェクトに対するコンディションのグループ化が行えます。
def person = new Person(name: "Fred", age: 33, sex: "male")
expect:
with(person) {
name == "Fred"
age == 33
sex == "male"
}
インタラクションのグループ化¶
with
メソッドはインタラクションのグループ化にも使用できます。
def service = Mock(Service)
app.service = service
when:
app.run()
then:
with(service) {
1 * start()
1 * act()
1 * stop()
}
ポーリングコンディション¶
AsyncConditions
とBlockingVariable(s)
を統合した、非同期のコードをテストするためのユーティリティを追加しました。
def person = new Person(name: "Fred", age: 22)
def conditions = new PollingConditions(timeout: 10)
when:
Thread.start {
sleep(1000)
person.age = 42
sleep(5000)
person.name = "Barney"
}
then:
conditions.within(2) {
assert person.age == 42
}
conditions.eventually {
assert person.name == "Barney"
}
Eclipse用の実験的なDSLサポート¶
Groovy EclipseがSpockのDSLを理解しやすいように、Groovy EclipseためのDSLディスクリプタを同封するようにしました。このディスクリプタは、IDEによって自動的に検出され有効になります。以下に例を示します。
// currently need to type variable for the following to work
Person person = new Person(name: "Fred", age: 42)
expect:
with(person) {
name == "Fred" // editor understands and auto-completes 'name'
age == 42 // editor understands and auto-completes 'age'
}
他の例では以下のようになります。
def person = Stub(Person) {
getName() >> "Fred" // editor understands and auto-completes 'getName()'
getAge() >> 42 // editor understands and auto-completes 'getAge()'
}
DSLのサポートは、Groovy Eclipse 2.7.1以降で使用できます。これは、Groovy Eclipseの設定で無効にすることもできます。
IntelliJ IDEA用の実験的なDSLサポート¶
Intellij IDEAがSpockのDSLを理解しやすいように、Intellij IDEAためのDSLディスクリプタを同封するようにしました。このディスクリプタは、IDEによって自動的に検出され有効になります。以下に例を示します。
def person = new Person(name: "Fred", age: 42)
expect:
with(person) {
name == "Fred" // editor understands and auto-completes 'name'
age == 42 // editor understands and auto-completes 'age'
}
他の例では以下のようになります。
def person = Stub(Person) {
getName() >> "Fred" // editor understands and auto-completes 'getName()'
getAge() >> 42 // editor understands and auto-completes 'getAge()'
}
DSLのサポートはIntelliJ IDEA 11.1以降で使用できます。
Specificationクラスの分割¶
spock.lang.Specification
クラスの一部を、2つのスーパークラスに引き上げました。ひとつはspock.lang.MockingApi
で、これにはモックに関連する全てのメソッドが含まれます。そして、org.spockframework.lang.SpecInternals
には、直接使用することを意図していない内部メソッドが含まれます。
notThrown
とnoExceptionThrown
の失敗メッセージの改善¶
単に例外を通知する代わりに、Specification.notThrown
とSpecification.noExceptionThrown
は、以下のような失敗メッセージを表示するようになりました。
Expected no exception to be thrown, but got 'java.io.FileNotFoundException'
Caused by: java.io.FileNotFoundException: ...
HamcrestSupport.expect
¶
spock.util.matcher.HamcrestSupport
クラスに新たなexpect
メソッドを追加しました。これを使用することで、thenブロック内のHamcrestのアサーションが、より読みやすくなります。
when:
def x = computeValue()
then:
expect x, closeTo(42, 0.01)
@Beta¶
最近追加されたクラスや、メソッドには@Betaアノテーションが付与されている場合があります。これは今後、互換性のない変更が行われる可能性があることを表しています。さらにこれが、ユーザーからの貴重なフィードバックを得る機会になることも期待しています(あなたのフィードバックをお待ちしています!)。多くの場合、@Betaは1回、または2回のリリース内で削除されます。
0.6¶
モッキングの改善¶
モックフレームワークでは、いくつかのケースでよりわかりやすい診断メッセージを提供するようにしました。
また、複数のレスポンスの定義をチェーンできるようになっています。以下は、最初のbarメソッドの呼び出しにIOException
をスローし、 次の呼び出しでは数字の1、2、3を返し、それ以降の呼び出しにはRuntimeException
をスローします。
foo.bar() >> { throw new IOException() } >>> [1, 2, 3] >> { throw new RuntimeException() }
foo.bar(*_)
のように、任意の引数リスト(空のリストを含む)と、一致させることが可能になりました。
また、Hamcrestを使用して、引数制約を指定できるようになっています。
import static spock.util.matcher.HamcrestMatchers.closeTo
...
1 * foo.bar(closeTo(42, 0.001))
JUnitルールサポートの拡張¶
org.junit.rules.MethodRule
(これはJUnit 4.9でdeprecatedになりました)を実装したルールに加え、org.junit.rules.TestRule
インタフェースを実装したルールのサポートを追加しました。また、JUnitの新たな@ClassRule
アノテーションのサポートも追加しています。さらにルールの定義を自動的に認識し、明示的に初期化しなくても動作するようになっています。これはデフォルトコンストラクタを使用し、Spockが自動的にルールを初期化します。@Unroll
アノテーションを使用したネーミングパターンは、@TestName
ルールや、その他一般的なルールにも適用されるようになりました。
SpockのTestRuleサポートに関する 課題 240 の制約を確認してください。
コンディションの表示の改善¶
2つのオブジェクトを==
演算で比較すると、これらは等しないにもかかわらず、文字列表現はまったく同じものになってしまいます。このような場合に、オブジェクトの型を出力するようにしました。
enteredNumber == 42
| |
| false
42 (java.lang.String)
JUnitのフィクスチャアノテーション¶
従来のSpcokのフィクスチャメソッドに加え(または代わりに)、JUnitの@Before
、@After
、@BeforeClass
そして@AfterClass
を使用してフィクスチャメソッドが定義できるようになりました。
Tapestry 5.3のサポート¶
Howard Lewis Shipからのコントリビュートにより、TapestryモジュールがTapestry 5.3 互換となりました。従来の5.x以前のバージョンも、まだサポートされています。
IBM JDKのサポート¶
IBMのJDKで検証を行いバグを回避をすることで、IBMのJDKで問題なく動作するようになりました。
JUnit互換の改善¶
org.junit.internal.AssumptionViolatedException
のハンドリングを追加しました。これにより、JUnitのAssume関連のAPIが問題なく動作するようになります。また、@Unroll
を付与したメソッドが、IDE上で警告とならないようになりました。
@Unroll
の改善¶
@Unroll
のネーミングパターンがアノテーションの引数だけでなく、メソッド名で指定できるようになりました。
@Unroll
def "maximum of #a and #b is #c"() {
expect:
Math.max(a, b) == c
where:
a | b | c
1 | 2 | 2
}
また、ネーミングパターンでプロパティアクセス、引数なしのメソッド呼び出しが使用できるようになっています。
@Unroll
def "#person.name.toUpperCase() is #person.age years old"() { ... }
さらに、@Unroll
アノテーションが、スペッククラスにも適用できるようにしました。この場合は、すべてのデータ駆動のフィーチャメソッドが展開実行されます。
@Timeout
の改善¶
@Timeout
アノテーションが、スペッククラスにも適用にも適用できるようになりました。この場合は、@Timeout
がすでに設定されているフィーチャメソッド除き、すべてのフィーチャメソッドにタイムアウトが適用されます。タイムアウトが付与されたメソッドは、通常のテストフレームワークのスレッドで実行されます。これは、スレッドローカルの状態に依存しているテストを行う場合に重要になることがあります(たとえばGrailsのインテグレーションテスト)。また、タイムアウトを強制することができるチャンスをより多くするために、スレッド中断の動作が改善されました。
タイムアウトが発生した場合にスローされる例外の中に、テスト実行のスタックトレースが含まれるようになっています。これにより、どのスタックでタイムアウトになったのか、簡単に把握できるようになります。
データテーブルのシンタックス改善¶
テーブルのセルを論理和の記号(||
)で、区切ることができるようになりました。これは、入力値と出力の期待値を、視覚的に区別するために使用できます。
...
where:
a | b || sum
1 | 2 || 3
3 | 1 || 4
Groovy 1.8/2.0のサポート¶
Spock 0.6ではGroovy 1.7、1.8、そして2.0それぞれに対応した、3つのバージョンを提供しています。これらの中から正しいバージョンを使用するようにしてください。例えば、Groovy 1.8を使用している場合は、spock-core-0.6-groovy-1.8を使用する必要があります(他のモジュールも同様です)。Groovy 2.0のバージョンはGroovyの2.0-beta-3-SNAPSHOTをベースにしており、http://m2repo.spockframework.orgからのみ利用可能です。Groovy 1.7と1.8のバージョンはMavenのセントラルリポジトリからも利用可能です。また次のバージョンからは、Groovy 1.7をサポートしない予定です。
Grails 2.0のサポート¶
SpockのGrailsプラグインを別のプロジェクトにしました。http://github.spockframework.org/spock-grailsで管理しています。このプラグインは、Grailsの1.3と2.0の両方をサポートしています。
Spock Grails pluginはGrails 2.0の新たなテストミックスインをすべてサポートしています。これにより既存のユニットテスト関連のクラスが非推奨になります(例えばUnitSpec)。ただしインテグレーションテストのために、IntegrationSpecは引き続き使用する必要があります。
Intellij IDEA連携¶
JetBrains の開発メンバーにより、データテーブルの周りのいくつか便利な機能が追加されました。まず、コードを再フォーマットすると、データテーブルが自動的にレイアウトされます。データ変数はこれまでのように”unknown”とは表示されません。さらに、これらの型はテーブルの値から型が推論されます(なんと!)。
Githubリポジトリ¶
すべてのソースコードをhttp://github.spockframework.org/へ移動しました。ここにはGrails Spock plugin、Spock Exampleプロジェクト、そしてSpock Web ConsoleがGithubのプロジェクトとして置いてあります。また、各種プレゼンテーション用の、スライドやサンプルコードも参照可能になっています(例えばこれ)。
Gradleビルド¶
SpockをGradleで構築するようにしました。Spockを自分自身でビルドする場合は、GitHub repoをクローンし、gradlew build
を実行することで簡単にビルドできます。事前にビルドツールをインストールしておく必要はありません。Spockをビルドするために必要な前準備は、JDKのインストール(1.5以上)のみです。