Karate Gatling report - is it possible to avoid url based aggregation? - karate

I just started to use Karate Gatling for performance tests and facing following problem:
I have a call for the search and would like to evaluate different types of search depending on the parameter e.G. https://example.com/search/facetedSearch
'*'
'keyword1'
'keyword1, keyword2' etc.
The feature file looks something like this:
#performance
Feature: Search
Background:
* url 'https://example.com/'
Scenario Outline: Search -> Simple search for a single word
Given path '/search/facetedSearch'
And param facetedSearchAdditionalFilter[searchAreaID] = -1
And param facetedSearchAdditionalFilter[searchKey] = '<SearchTermSimple>'
When method post
Then status 200
And assert iNumHits >= iNumHitsExpected
Examples:
| read('../testData/performanceTestData.csv') |
Scenario: Search -> Simple search for *
Given path '/search/facetedSearch'
And param facetedSearchAdditionalFilter[searchAreaID] = -1
And param facetedSearchAdditionalFilter[searchKey] = '*'
When method post
Then status 200
And assert iNumHits >= iNumHitsExpected
Scenario Outline: Search -> Search for multiple words
Given path '/search/facetedSearch'
And param facetedSearchAdditionalFilter[searchAreaID] = -1
And param facetedSearchAdditionalFilter[searchKey] = '<SearchTermMultiple>'
When method post
Then status 200
And assert iNumHits >= iNumHitsExpected
Examples:
| read('../testData/performanceTestData.csv') |
I would like to evaluate different types of search separately, as the performance is significantly different. What gatling does - it aggregates all different types of search in one result - "POST /search/facetedSearch".
Is there a possibility to let evaluate every type of search individually in one run?
Thanks in advance,
Sergej

Yes, refer the docs on using a custom nameResolver: https://github.com/karatelabs/karate/tree/master/karate-gatling#nameresolver
For your case you should be able to call req.getParam("facetedSearchAdditionalFilter[searchKey]")[0] or something similar. Or you could choose to use an additional header.

Related

Calling feature file within another feature file using tags [duplicate]

We have a feature A with several scenarios. And we need one scenario from that file. Can we call it in our feature B?
No. You need to extract that Scenario into a separate*.feature file and then re-use it using the call keyword.
EDIT: Karate 0.9.0 onwards will support being able to call by tag as follows:
* def result = call read('some.feature#tagname')
To illustrate the answer from Karate-inventor Peter Thomas with an example:
Given a feature-file some.feature with multiple scenarios tagged by a tag-decorator:
#tagname
Scenario: A, base case that shares results to e.g. B
// given, when, then ... and share result in a map with keyword `uri`
* def uri = responseHeaders['Location'][0]
#anotherTag
Scenario: X, base case that shares results to e.g. B
// given, when, then ... and share result in a map with keyword `createdResourceId`
* def createdResourceId = $.id
In another feature we can call a specific scenario from that feature by its tag, e.g. tagname:
Scenario: B, another case reusing some results of A
* def result = call read('some.feature#tagname')
* print "given result of A is: $result"
Given path result.uri + '/update'
See also: demo of adding custom tags to scenarios

Can Karate generate multiple query parameters with the same name?

I need to pass multiple query parameters with the same name in a URL, but I am having problems getting it to work with Karate. In my case, the URL should look like this:
http://mytestapi.com/v1/orders?sort=order.orderNumber&sort=order.customer.name,DESC
Notice 2 query parameters named "sort". I attempted to create these query string parameters with Karate, but only the last "sort" parameter gets created in the query string. Here are the ways I tried to do this:
Given path 'v1/orders'
And param sort = 'order.orderNumber'
And param sort = 'order.customer.name,DESC'
And header Authorization = authInfo.token
And method get
Then status 200
And:
Given path 'v1/orders'
And params sort = { sort: 'order.orderNumber', sort: 'order.customer.name,DESC' }
And header Authorization = authInfo.token
And method get
Then status 200
And:
Given path 'v1/order?sort=order.orderNumber&sort=order.customer.name,DESC'
And header Authorization = authInfo.token
And method get
Then status 200
The first two ways provide the same query string result: ?sort=order.customer.name%2CDESC
The last example does not work because the ? get encoded, which was expected and explained in this post - Karate API Tests - Escaping '?' in the url in a feature file
It's clear that the second "sort" param is overriding the first and only one parameter is being added to the URL. I have gone through the Karate documentation, which is very good, but I have not found a way to add multiple parameters with the same name.
So, is there a way in Karate to set multiple URL query parameters with the same name?
Yes you can generate multiple query parameters with the same name in karate
All values of similar key should be provided in an array.
Given path 'v1/orders'
And params {"sort":["order.orderNumber","order.customer.name,DESC"]}
And header Authorization = authInfo.token
And method get
Then status 200
And for setting single parameter using param it will be like
And param sort = ["order.orderNumber","order.customer.name,DESC"]

Same asserts for every scenario can be put in a separate file to avoid duplication in karate?

Here are two scenarios , One after the other
Scenario: Positive - Create a discount with ABSOLUTE discount and ROOM_NIGHT_PRICE and search
Given url baseUrl + SEARCH
And request changes
When method post
Then status 200
And match $.data.hotels[0].transaction_discount.discounts[0].discount_id == discountId
And match $.data.hotels[0].transaction_discount.discounts[0].code == couponCode
And match $.data.hotels[0].transaction_discount.discounts[0].discount_value == incentive_value
And match $.data.hotels[0].transaction_discount.discounted_sell_price == (sellPrice-incentive_value)
Scenario: Positive - Create a discount with ABSOLUTE discount and TRANSACTION_PRICE and search
Given url baseUrl + SEARCH
And request changes
When method post
Then status 200
And match $.data.hotels[0].transaction_discount.discounts[0].discount_id == discountId
And match $.data.hotels[0].transaction_discount.discounts[0].code == couponCode
And match $.data.hotels[0].transaction_discount.discounts[0].discount_value == incentive_value
And match $.data.hotels[0].transaction_discount.discounted_sell_price == (sellPrice-incentive_value)
If you notice that assertions are same for these scenarios , I have similar 20 scenarios with exactly same assertions , Can I put it in a separate file to avoid duplication and easy to maintain ?
If Yes then how ?
If No then is there any other way to avoid duplication in karate
I don't see any change on your request either.
If only change in your scenarios are payload
You can try using Scenario Outline:
and pass different payloads from Examples: table
Scenario Outline: Positive - Create a discount and search
Given url baseUrl + SEARCH
And request <changes>
When method post
Then status 200
And match $.data.hotels[0].transaction_discount.discounts[0].discount_id == discountId
And match $.data.hotels[0].transaction_discount.discounts[0].code == couponCode
And match $.data.hotels[0].transaction_discount.discounts[0].discount_value == incentive_value
And match $.data.hotels[0].transaction_discount.discounted_sell_price == (sellPrice-incentive_value)
Examples:
| changes |
|RNP_PAYLOAD|
|TXP_PAYLOAD|
you can create these payloads instances in Background:, this could help you avoid scenario duplication.
OR
If your intention is still to have this on a separate file
You can create a feature file which takes both expected and actual JSON as an input and perform match operation in it.
Then you can call that feature file in all of your scenarios passing the values to the calling feature.

Can we use '#ContinueNextStepsOnException' to run all the steps in the Karate script instead of karate.match(actual, expected)

I have a response with hundreds of attributes while matching the attributes the scripts getting failed and further steps are not getting executed. because of this we have to validate the same case multiple times to validate the attribute values. is they a option like #ContinueNextStepsOnException to execute all the steps and it is hard to script using karate.match(actual, expected) for more than 100 attributes I have give actual and expected values if in case of any failure to continue.
No, there is no such option. If your scripts are getting failed - it is because Karate is doing its job correctly !
If you feel you want to skip certain fields, you can easily do so by using match ... contains syntax.
I think you are using multiple lines instead of matching the entire JSON in one-line which you can easily do in Karate. For example:
* def response = { a: 1, b: 2 }
# not recommended
* match response.a == 1
* match response.b == 2
# recommended
* match response == { a: 1, b: 2 }
Is it so hard to create the above match, even in development mode ? Just cut and paste valid JSON, and you are done ! I have hardly ever heard users complain about this.

Can we call a scenario from one feature in another using karate?

We have a feature A with several scenarios. And we need one scenario from that file. Can we call it in our feature B?
No. You need to extract that Scenario into a separate*.feature file and then re-use it using the call keyword.
EDIT: Karate 0.9.0 onwards will support being able to call by tag as follows:
* def result = call read('some.feature#tagname')
To illustrate the answer from Karate-inventor Peter Thomas with an example:
Given a feature-file some.feature with multiple scenarios tagged by a tag-decorator:
#tagname
Scenario: A, base case that shares results to e.g. B
// given, when, then ... and share result in a map with keyword `uri`
* def uri = responseHeaders['Location'][0]
#anotherTag
Scenario: X, base case that shares results to e.g. B
// given, when, then ... and share result in a map with keyword `createdResourceId`
* def createdResourceId = $.id
In another feature we can call a specific scenario from that feature by its tag, e.g. tagname:
Scenario: B, another case reusing some results of A
* def result = call read('some.feature#tagname')
* print "given result of A is: $result"
Given path result.uri + '/update'
See also: demo of adding custom tags to scenarios