web-dev-qa-db-ja.com

Spockの@Sharedアノテーションを静的フィールドよりも優先する必要があるのはいつですか?

追加することはあまりありません。質問全体がタイトルにあります。

Spock仕様で使用されているFooクラスのこれら2つのインスタンスについて考えてみます。

@Shared Foo foo1 = new Foo()

static Foo foo2 = new Foo()

全体的に、@Sharedアノテーションの背後にある考え方は知っていますが、言語機能を使用する方が良いと思います。この場合はstaticフィールドになります。

どちらか一方を優先する特定のケースはありますか、それとも好みの問題ですか?

18
topr

スポックは、表現力明快さがすべてです。

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なども参照してください。同じ目的で存在します)

15
kazanaki

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が原因です。

9
Valya

より包括的なアプローチとして、出力を使用したサンプルテストを次に示します。

_@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句でアクセスすることもできます。これらの句は、各テストケースで前にリストされている他の句の前に実行されます。

2
Igor

静的フィールドは定数にのみ使用してください。それ以外の場合は、共有に関するフィールドがより明確に定義されているため、共有フィールドが推奨されます。

0
jun zhou