Spock翻訳Data Driven Testing

7029 ワード

Data Driven Testing


通常、同じテストコードを複数回実行することは有用であり、異なる入力と予想される結果である.spockデータ駆動テストサポートにより、彼は第1クラスの特性になります.

Introduction


Suppose we want to specify the behavior of the Math.max method:
class MathSpec extends Specification {
    def "maximum of two numbers"() {
        expect:
        // exercise math method for a few different inputs
        Math.max(1, 3) == 3
        Math.max(7, 4) == 7
        Math.max(0, 0) == 0
    }
}

この方式は簡単な例でこれに似ているが、コードとデータが混在しているという潜在的な欠点があるが、データを独立して変更することは容易ではなく、外部ソースから同じコードを自動的に生成したり、取得したりすることは容易ではない.直ちにクリーンアップに失敗した入力をクリーンアップできず、同じコードを複数回実施することは、分離方法を実行する方法として同じ分離から不利である.spockのデータ駆動サポートは、これらの問題を解決しようとしています.開始する前に、上記のコードを再構築して、データ駆動特性メソッドを使用します.まず,ハードコーディングinterge値を置換する3つの方法パラメータを紹介する.
class MathSpec extends Specification {
    def "maximum of two numbers"(int a, int b, int c) {
        expect:
        Math.max(a, b) == c

        ...
    }
}

この論理テストを完了しますが、データ値が使用される必要があります.こうしてwhere blockの置き方の最後に.この簡単な例では、where:blockはデータテーブルを持っています.

Data Tables


Data tables are a convenient way to exercise a feature method with a fixed set of data values:
class Math extends Specification {
    def "maximum of two numbers"(int a, int b, int c) {
        expect:
        Math.max(a, b) == c

        where:
        a | b | c
        1 | 3 | 3
        7 | 4 | 4
        0 | 0 | 0
    }
}

データテーブルは、特定のグループのデータを使用する特性方法を容易に実施するためのものである.
where:a | _1 | _7 | _0 | _テーブルの最初の行は、データヘッダと呼ばれ、変数を定義します.サブローは、データ行と呼ばれ、対応するデータを保持します.各ローについて、プロパティメソッドが1回実行されます.反復法と呼ばれます.反復メソッドが失敗した場合、他の反復が実行されることを意味します.すべての失敗が報告されます.

Isolated Execution of Iterations


反復式独立の相互間同一の分割特性からの方法.各反復はspecクラスから自分のインスタンスを取得します.setup cleanupは、各反復の実行前後にそれぞれ呼び出されます.
共有オブジェクト反復間の順序で共有@Sharedまたは静的フィールドを使用するオブジェクト反復間
ヒント@Sharedと静的フィールドのみがwhere:blockにアクセスできます.これらのオブジェクトは、他の方法にも共有されることに注意してください.同じ方法でオブジェクトを共有するのは良い方法ではありません.もしあなたがこの問題を考えるならば、思考はすべての方法を隔離したspecに入れて、すべて同じファイルに処理することができます.この実装は、いくつかのテンプレートコードのコストからよりよく分離される.

Syntactic Variations

class DataDriven extends Specification {
    def "maximum of two numbers"() {
        expect:
        Math.max(a, b) == c

        where:
        a | b || c
        3 | 5 || 5
        7 | 0 || 7
        0 | 0 || 0
    }
}

上のコードはいくつかの面で調整できます.まず、where:blockからすべてのデータ変数が定義され、このメソッドパラメータがコミットされます.次に,入力と期待出力を分離して二重線を用いて仮想設定を分離できる.これを使用すると、コードはこのようになります.

Reporting of Failures


maxを実現する方法には誤りがあり,そのうちの1つは反復に失敗したと想定する.
2つの数字の中で最大の数字が失敗しました
明らかな問題は、反復に失敗し、データ値が何であるかです.私たちの例では、2番目の反復失敗を指摘するのは非常に難しい.他の時はもっと難しいかもしれないし、不可能かもしれない.どんな例でも、spockが大声でどの失敗が非常に良いかを明らかにできれば、失敗を報告するだけです.@Unroll注記のターゲットです

Method Unrolling


メソッド注記@Unrollを使用すると、反復プロセスが独立してレポートされます.なぜ@Unrollは値を黙らないのですか?1つの理由は、いくつかの実行環境が、テスト方法の数を事前に通知し、実際の数の問題を決定することを期待しているからである.寧の1つの原因は、この注釈がテスト報告の数を極めて大きく変えることができ、賢明ではない可能性があるからである.注意unrollingはメソッドの実行に影響しません.彼は報告書の中で交替しただけだ.実行環境に依存して出力する
maximum of two numbers[0]   PASSED

maximum of two numbers[1]   FAILED

Math.max(a, b) == c
    |    |  |  |  |
    |    7  0  |  7
    42         false

maximum of two numbers[2] PASSEDThis tells us that the second iteration (with index 1) failed. With a bit of effort, we can do even better:
@Unroll
def "maximum of #a and #b is #c"() { ... }

これは私たちに2番目の反復の失敗を教えてくれて、インデックスは1で、少しの努力に従って、私たちはもっとよくすることができます.このメソッド名は、1つ前の#記号、関連データ変数a b cによって、出力されると、特定の値が置換されることを示すプレースホルダを使用する.
maximum of 3 and 5 is 5   PASSED
maximum of 7 and 0 is 7   FAILED

Math.max(a, b) == c
    |    |  |  |  |
    |    7  0  |  7
    42         false

maximum of 0 and 0 is 0   PASSED

maxメソッドが7と0の入力に失敗したことが一目でわかります.詳細はon Unrolled Method Nameで

Data Pipes


Data tables aren’t the only way to supply values to data variables. In fact, a data table is just syntactic sugar for one or more data pipes:
...
where:
a << [3, 7, 0]
b << [5, 0, 0]
c << [5, 7, 0]

データテーブルは、データ変数を提供する方法の一つであることを知らない.実際には、1つのデータテーブルは1つの構文糖が1つ以上のデータパイプであるだけです.1つのデータパイプでleft-shift(<必要に応じて次の値を取得します.

Multi-Variable Data Pipes


@Shared sql = Sql.newInstance("jdbc:h2:mem:", "org.h2.Driver")
データプロバイダが反復ごとに複数の値を返す場合.複数のデータ変数が同期して接続されます.この構文はgroovyマルチタスクに似ていますが、左側のカッコの代わりにカッコを使用します.
def "maximum of two numbers"() {
    ...
    where:
    [a, b, c] << sql.rows("select a, b, c from maxdata")
}

関心のないデータ値は無視して下線を使うことができます...
where:
[a, b, _, c] << sql.rows("select * from maxdata")

Data Variable Assignment


1つのデータ変数は直接1つの値を割り当てます...
where:
a = 3
b = Math.random() * 100
c = a > b ? a : b

割り当ては各反復で再評価される.上に示すように、右の部分割当ては、他のデータ変数に関連付けることができます.
...
where:
row << sql.rows("select * from maxdata")
// pick apart columns
a = row.a
b = row.b
c = row.c

Combining Data Tables, Data Pipes, and Variable Assignments


Data tables,data pipes,and variable assignments can be combined as needed:データテーブルデータパイプの複数の変数の割り当てが必要とされています...
where:
a | _
3 | _
7 | _
0 | _

b << [5, 0, 0]

c = a > b ? a : b

Number of Iterations


反復間の数がどれだけのデータに依存するかは可変です.同じ方法を連続的に実行すると、異なる数の反復が生成されます.データプロバイダが同業者よりも値を速く実行すると、例外が発生します.複数の変数の割り当ては反復数に影響しません.1つのwhere:blockは、割り当てが正確に反復を生成することのみを含む.

Closing of Data Providers


After all iterations have completed, the zero-argument close method is called on all data providers that have such a method.すべての反復が完了すると、パラメータのないクローズメソッドが呼び出され、すべてのデータプロバイダでこのようなメソッドが呼び出されます.

More on Unrolled Method Names


一分unrolledメソッド名ルートgrooyの文字列は似ています.次の違いを除きます.表現は$の代わりに#がマークされ、${...}に等しくありません.構文式は、Personクラスに名前とageのみがサポートされ、データ型がpersonの変数のみが呼び出されます.次のチェック・メソッド名は、次のとおりです.
def "#person is #person.age years old"() { ... } // property access
def "#person.name.toUpperCase()"() { ... } // zero-arg method call

Non-string values (like #person above) are converted to Strings according to Groovy semantics.
The following are invalid method names:
def "#person.name.split(' ')[1]" { ... } // cannot have method arguments
def "#person.age / 2" { ... } // cannot use operators

If necessary, additional data variables can be introduced to hold more complex expression:
def "#lastName"() {
    ...
    where:
    person << ...
    lastName = person.name.split(' ')[1]
}
  • アイデアの背後にある実行方法パラメータはIDEによってよりよくサポートされている.その後、最新バージョンのIntelliJ IDEAは、データ変数を自動的に認識し、データテーブルの値からタイプ
  • を推定します.
  • 例えば、1つの特性方法は、setup:blockでデータ変数を使用することができるが、他の任意の条件
  • では使用できない.
  • groovy構文は、メソッド名の
  • で$記号を実行しません.