はじめに
前回(#04 Defining Data)は、色々なデータの定義の仕方について、確認しました。
今回は、Karate おける Assert の仕方について、確認してみます。
テスト実行時の期待値の確認で利用する内容です。
Assertの仕方
Matching
まずは、変数の一致/不一致を確認する内容です。
Scenario: Basic Matching
* def data1 = {name: 'Bob', age: 2}
* def data2 = {age: 2, name: 'Bob'}
* match data1 == data2
* def data3 = {name: 'Bob', age: 2}
* match data3 != {name: 'Bob', age: 3}
-
match A == B
で、値の一致を確認しています。 -
match A != B
は、値の不一致の確認です。
至極、基本的な内容ですね。
Fuzzy Matching 1
Karate では、**「Fuzzy Matching」**と呼ばれている記法があります。
固有の値を指定するのではなく、データの有無や型で判定を行う内容になります。
これを使うと、テストで動的なデータを生成している場合などに便利です。
Scenario: Fuzzy Matching 1
# ignore
* def test = {id: '001', name: { first: 'John', last: 'Smith' }, age: 20}
* match test == {id: '001', name: { first: '#ignore', last: 'Smith' }, age: 20}
#ignore
は、データの比較を無視します。
# null / notnull
* def test = {id: '001', name: null}
* match test == {id: '#notnull', name: '#null'}
そのままではありますが、
-
#null
は 値がnullである ことの確認 -
#notnull
は 値がnullではない ことの確認
ですね。
# present / notpresent
* def test = {id: '001', name: 'Bob'}
* match test == {id: '001', name: '#present', age: '#notpresent'}
-
#present
は 何かしらの値が存在すること ことの確認(値がnullの場合も可) -
#notpresent
は キーを含め、そのパラメータが存在しない ことの確認
となります。
#null/#notnull
と #present/#notpresent
の違いは、以下を確認すると分かりやすいかと思います。
# compare #null/#notnull, ##null/##null, #present/#notpresent
* def foo = { }
* match foo != {a: '#null'}
* match foo == {a: '##null'}
* match foo != {a: '#notnull'}
* match foo == {a: '##notnull'}
* match foo == {a: '#notpresent'}
* def foo = {a: null}
* match foo == {a: '#null'}
* match foo == {a: '##null'}
* match foo == {a: '#present'}
* def foo = {a: 1}
* match foo == {a: '#notnull'}
* match foo == {a: '##notnull'}
* match foo == {a: '#present'}
ここでさらに、##
という記述があります。
##
は、キーはオプション(存在しないかもしれない)、もしくは、値がnullでも許容する、という意味になります。
これを利用すると、以下のような違いが出てきます。
-
{a: '#null'}
の場合は、キーであるa
は存在していて、値がnullの場合に「True」となります。 -
{a: '##null'}
の場合は、キーであるa
を含めてパラメータ自体存在しないか、値がnullの場合に「True」となります。 -
{a: '##null'}
は、{a: '#notpresent'}
と同じ意味になります。
ちなみに、#ignore
、#null / #notnull
、#present / #notpresent
などは、**「Marker」**と呼ばれています。
Fuzzy Matching 2
Fuzzy Matching は、型の特定も可能です。
数値/文字列/bool値だけでなく、配列やオブジェクトなどの型も確認できます。
さらに、正規表現なども指定できます。
Scenario: Fuzzy Matching 2
# number
* def test = {foo: 1}
* match test == {foo: '#number'}
# string
* def test = {foo: 'test'}
* match test == {foo: '#string'}
# boolean
* def test = {foo: true}
* match test == {foo: '#boolean'}
# array
* def test = {foo: [1, 2]}
* match test == {foo: '#array'}
# object
* def test = {foo: {bar: 'baz'}}
* match test == {foo: '#object'}
# regex
* def test = {foo: 'test123'}
* match test == {foo: '#regex [a-z0-9]{7}'}
# uuid
* def test = {id: 'a9f7a56b-8d5c-455c-9d13-808461d17b91'}
* match test == {id: '#uuid'}
Validation Expressions
match
では、数式による判定も可能です。
ここまでできれば、かなりチェックの幅も広がります。
Scenario: Validation Expressions
* def month = {value: 3}
* match month == {value: '#? _ > 0 && _ < 13'}
* def min = 1
* def max = 12
* match month == {value: '#? _ >= min && _ <= max'}
* def isValid = function(v) { return v >= 1 && v <= 12 }
* match month == {value: '#? isValid(_)'}
まとめ
今回は、単純な値の一致判定だけでなく、Fuzzy Matching/Validation Expressions などの柔軟な判定方法を確認してみました。
これらの判定方法を把握しておけば、大抵のJSONデータは、簡単にチェックができそうです。