Cheat sheet for Karate Assertions and matching
Bonjour TestCommunity!!
I hope you enjoyed reading my blogs as much as I enjoyed writing them.
So here I am, with an intriguing subject that focuses on the most crucial component in API Testing and Automation.
Any guesses 🙄??? — — Yes! Its Assertions & Matching.😀
Fun Fact: Did you know Karate DSL is famous for its robust assertions techniques against JSON and XML response payloads???
Do you want to see various techniques of assertions and matching using this creative open-source framework?
Let’s have a look at a few techniques and examples in the section below—
Technique 1 —
Assert: is used when you want to evaluate a condition in the form of Boolean values i.e. True or False.
“assert” keyword is used to include assertions in the script.
The entire expression to the right of the assert keyword will be evaluated as a single expression.
Example 1: Match absolute value with the response value.
API- https://reqres.in/api/users/2
* assert response.data.id == 2* assert response.data.first_name == 'Janet'
Example 2: Assert the concatenated value obtained from response.
* def name = response.data.first_name* def surname = response.data.last_name* assert name + surname == 'JanetWeaver'
Example 3: Assertion can be done with concatenation of string and numeric value.
* def name = response.data.first_name* def id = response.data.id* assert name + id == 'Janet2'
Example 4: Dynamically add numeric values and assert with expected value.
API: https://reqres.in/api/users?page=2
* def perPage = response.per_page* def totalPages = response.total_pages* print perPage, totalPages* print perPage + totalPages# 6 + 2 = 8* assert perPage + totalPages == 8
Regardless of the fact that assertions in KarateDsl are highly versatile, “assert” keyword is rarely used in test scripts.
The “match” method is often used to address the need for robust assertions against JSON and XML response payloads.
Technique 2 —
Fuzzy Matching: is designed to match complicated JSON or XML payloads dynamically.
This technique is appropriate when particular fields in a response need to be validated or ignored.
Regular-expression (regex) can also be used to verify that the actual value matches the expected pattern.
All fuzzy matchers are listed below:
- Expected datatypes — #string, #number, #boolean, #array, #object.
- Presence of the value — #present, #notpresent.
- Value is null or not null — #null, #notnull.
- Regex can be used for string — #regex STR.
- Advanced array validation — #[Num] EXPR.
- String value to conform to the UUID format — #uuid.
- Ignore or skip comparison of a key despite its value is available — #ignore.
- Even JavaScript expression ‘EXPR’ can be evaluated to true — #? EXPR.
- Dynamic/defined value — (#EXPR).
- Optional field (key is optional or that the value can be null) can be defined by adding a #(hash) as a prefix— ##string, ##number, ##boolean etc.
Refer to the code snippet below to understand and use the various matchers from the specified list-
* match response.page == '#number'
# OR
* def page = 2* match response.page == '#(page)'* match response == {per_page:'#notnull', total:'#present', total_pages: '#ignore', data:'#array', support: '##object'}* match response.data[*] contains {id:'#number? _ > 0', email:'#regex .+@reqres.in', first_name:'#string', last_name:'#string', avatar: '#string'}#########################################
Note: Regex annotations are as follows:
.+ - is used to escape string
^ - start of string
[0-9]* - 0+ digits
[.]? - an optional period
[0-9]{2} - two digits
$ - end of string
In the preceding example, I have covered nearly all fuzzy matchers.
Hence, the fuzzy matching technique has brought us a lot of flexibility and ease in asserting complex payloads just by employing a keyword rather than creating entire code logic.
Technique 3 —
Match: is often used to address complex assertion requirements for JSON and XML response payloads.
“match” keyword is used to implement matching.
It supports fields matching irrespective of its order.
This technique not just supports fuzzy matching but also can be used in case of absolute match(==), to check if a particular field(s) should not match(!=), presence of desired keys by using contains (only/any/deep/!contains) ,iterate over each element present inside an array (match each) and even match response header (match header — alternatively can be used
responseHeaders
)It offers wide range of matches like
match ==
,match !=
,match contains
,match contains only
,match contains any
,match contains deep
,match !contains
,match each
,match header.
API: https://reqres.in/api/users?page=2
Sample response:
{"page": 2,"per_page": 6,"total": 12,"total_pages": 2,"data": [{"id": 7,"email": "michael.lawson@reqres.in","first_name": "Michael","last_name": "Lawson","avatar": "https://reqres.in/img/faces/7-image.jpg"},{"id": 8,"email": "lindsay.ferguson@reqres.in","first_name": "Lindsay","last_name": "Ferguson","avatar": "https://reqres.in/img/faces/8-image.jpg"},{"id": 9,"email": "tobias.funke@reqres.in","first_name": "Tobias","last_name": "Funke","avatar": "https://reqres.in/img/faces/9-image.jpg"},{"id": 10,"email": "byron.fields@reqres.in","first_name": "Byron","last_name": "Fields","avatar": "https://reqres.in/img/faces/10-image.jpg"},{"id": 11,"email": "george.edwards@reqres.in","first_name": "George","last_name": "Edwards","avatar": "https://reqres.in/img/faces/11-image.jpg"},{"id": 12,"email": "rachel.howell@reqres.in","first_name": "Rachel","last_name": "Howell","avatar": "https://reqres.in/img/faces/12-image.jpg"}],"support": {"url": "https://reqres.in/#support-heading","text": "To keep ReqRes free, contributions towards server costs are appreciated!"}}
Below code snippet consist of few examples :
# 1. Absolute match by using "==" to strictly existence of check all keys* def page = 2* match response.page == '#(page)'# 2. contains: match existence of some keys* match response contains {per_page:'#notnull', total_pages: '#ignore', data:'#array', support: '##object'}# 3. !contains: assert that specified key does not exists* def available_ids = karate.jsonPath(response,"$..['id']")* print available_ids* match available_ids !contains [2]# 4. contains only: assert that all array elements are present but in any order* match available_ids contains only [10,9,7,8,12,11]# 5. contains any: assert any of the given array elements are present* match available_ids contains any [10,9,7,8]# 6. match each: Iterate over all elements in a JSON array using the each modifier* match each response.data[*] == {id:'#number? _ > 0', email:'#regex .+@reqres.in', first_name:'#string', last_name:'#string', avatar: '#string'}
# 7. contains deep: is an alternative of "match contains" as it supports matching of nested nested lists or objects i.e. match some values in the various "trees" of data* def nested_data = karate.jsonPath(response,"$..['id','first_name']")* print nested_data* match response.data contains deep"""[{ "id": 7,"first_name": "Michael"},{"id": 8,"first_name": "Lindsay"},{"id": 9}]"""
Karate also provides Shortcuts for contains, following table depicts the same:
It’s time for me to wrap up this blog with the belief that you have gained a better understanding of why Karate is considered to have powerful assertion techniques that may quickly validate a complex response with just a few keywords.
Is this series helpful ? Let me know your thoughts in the comments section. To get the latest updates, subscribe to my Medium channel. You can also connect and follow me on LinkedIn.
🎊 🎉🌟Until then, Stay safe & usher in 2022 with a bang! Adieu!!🌟🎊 🎉