追加することはあまりありません。質問全体がタイトルにあります。
Spock仕様で使用されているFooクラスのこれら2つのインスタンスについて考えてみます。
@Shared Foo foo1 = new Foo()
static Foo foo2 = new Foo()
全体的に、@Shared
アノテーションの背後にある考え方は知っていますが、言語機能を使用する方が良いと思います。この場合はstatic
フィールドになります。
どちらか一方を優先する特定のケースはありますか、それとも好みの問題ですか?
スポックは、表現力と明快さがすべてです。
StaticはJavaキーワードで、クラスの内部のみを表示します(このフィールドはすべてのインスタンスで同じです)
@ Sharedは、この変数がすべての機能メソッドで同じであることを読者に伝えるSpock機能です。これは、特にユニットテスト専用の指示であり、ユニットテストを読みやすくします。
メインのSpockブロックについても同じことが言えます。あなたがそれについて考えれば、彼らは実際にはコードの何も変更しません。
public void myScenario(){
int a = 2 + 3;
assertEquals(5,a);
}
public void "simple addition scenario"(){
when: "I add two numbers"
int a = 2 +3
then: "I expect the correct result"
a == 5
}
両方の単体テストは技術的にまったく同じことを行います。 2つ目は意図をより明確に示しています。 when:およびthen:ラベルは、その意図を明確にすること以外、コードで実際には何もしません。
つまり、@ Sharedはテストを読みやすくしています。 (@ Issue、@ Titleなども参照してください。同じ目的で存在します)
JUnitとは逆に、フィールド変数staticを宣言して、それに値を割り当てる必要があります。
@BeforeClass
public static void setupClass()
そのため、各メソッドではなくテストスイートごとに1回だけ初期化され、Spockではインスタンスフィールド変数を使用して@Shared
。
次の例について考えてみます。
class SharedTestSpec extends spock.lang.Specification {
@Shared
def shared = shared()
def shared() {
"I came from ${this.class.simpleName}"
}
def 'Test one'() {
given:
println("test one, shared: $shared")
expect: true
}
def 'Test two'() {
given:
println("test two, shared: $shared")
expect: true
}
}
class SubclassSpec extends SharedTestSpec {
@Override
def shared() {
println("They've got me!")
"I came from ${this.class.simpleName}"
}
}
SubclassSpecを実行すると、次の出力が得られます。
test one, shared: I came from SubclassSpec
test two, shared: I came from SubclassSpec
They've got me!
ただし、印刷順序を説明することはできませんが、それはASTが原因です。
より包括的なアプローチとして、出力を使用したサンプルテストを次に示します。
_@Unroll
class BasicSpec extends Specification {
int initializedVariable
int globalVariable = 200
static int STATIC_VARIABLE = 300
@Shared
int sharedVariable = 400
void setup() {
initializedVariable = 100
}
void 'no changes'() {
expect:
printVariables()
/*
initializedVariable: 100
globalVariable: 200
STATIC_VARIABLE: 300
sharedVariable: 400
*/
}
void 'change values'() {
setup:
initializedVariable = 1100
globalVariable = 1200
STATIC_VARIABLE = 1300
sharedVariable = 1400
expect:
printVariables()
/*
initializedVariable: 1100
globalVariable: 1200
STATIC_VARIABLE: 1300
sharedVariable: 1400
*/
}
void 'print values again'() {
expect:
printVariables()
/*
initializedVariable: 100
globalVariable: 200
STATIC_VARIABLE: 1300
sharedVariable: 1400
*/
}
private void printVariables() {
println "initializedVariable: $initializedVariable"
println "globalVariable: $globalVariable"
println "STATIC_VARIABLE: $STATIC_VARIABLE"
println "sharedVariable: $sharedVariable\n"
}
}
_
私にとって驚くべきことは、クラスのsetup()
メソッドAS WELL内の変数がグローバルなインスタンス化変数として両方のテストでリセットされることです(おそらく、クラスが各テストケースで再インスタンス化されるためです)。その間、static
および_@Shared
_変数は期待どおりに機能します。その結果、後の2つはwhere
句でアクセスすることもできます。これらの句は、各テストケースで前にリストされている他の句の前に実行されます。
静的フィールドは定数にのみ使用してください。それ以外の場合は、共有に関するフィールドがより明確に定義されているため、共有フィールドが推奨されます。