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

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.

Related

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

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.

Karate netty/mock schema match not working [duplicate]

I have a request that is hitting my mock server... the request is in json, but one of the values is a string of about 2,000+ characters.. I am wanting to match the request if the string value (of 2,000+ characters) contains a specific substring value...
for example:
Scenario:
pathMatches('/callService') &&
methodIs('post') && request.clientDescription contains 'blue eyes'
(request.clientDescription = string of 2,000+ characters)
It seems that it does not like the key word contains and I can't seem to find any information on the syntax I would use to search through a given string in a request and see if it contains a specific value.
I understand that I could try to match the entire string value using '==', but I am looking for a way to only match if it contains a substring.
Here's a tip, whatever you see on the right of Scenario: is pure JavaScript, and methodIs() etc. happen to be pre-defined for your convenience.
So this should work, using String.includes()
Scenario: request.clientDescription.includes('blue eyes')
Also please refer this answer for other ideas: https://stackoverflow.com/a/57463815/143475
And one more: https://stackoverflow.com/a/63708918/143475
It did not seem to like when I added "&& request.clientDescription.includes('blue eyes')" in the Scenario, but it did lead me in the right direction, and I did find a solution. thanks!
Error : after adding String.includes to Scenario:
com.intuit.karate - scenario match evaluation failed: evaluation (js) failed: pathMatches('/callService') &&
methodIs('post') && request.clientDescription.includes('blue eyes'), javax.script.ScriptException: TypeError: request.clientDescription.includes is not a function in at line number 2
stack trace: jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(NashornScriptEngine.java:470)
A Solution:
defined a function in the background using karate.match
Code Example of Solution:
Background:
* def isBlueEyed = function(){return karate.match("request.clientDescription contains 'Blue Eyes'").pass}
Scenario:
pathMatches('/callService') &&
methodIs('post') && isBlueEyed()
* def response = read('./***/***/**')

Does gorm interpret the content of a struct with a logical OR?

New to SQL, I am writing as an exercise an API middleware that checks if the information contained in some headers match a database entry ("token-based authentication"). Database access is based on GORM.
To this, I have defined my ORM as follows:
type User struct {
ID uint
UserName string
Token string
}
In my middleware I retrieve the content of relevant headers and end up with the variables userHeader and tokenHeader. They are supposed to be matched to the database in order to do the authentication.
The user table has one single entry:
select * from users
// 1,admin,admintoken
The authentication code is
var auth User
res := db.Where(&User{UserName: userHeader, Token: tokenHeader}).Find(&auth)
if res.RowsAffected == 1 {
// authentication succeeded
}
When testing this, I end up with the following two incorrect results (other combinations are correct):
with only one header set to a correct value (and the other one not present) the authentication is successful (adding the other header with an incorrect value is OK (=auth fails))
no headers set → authentication goes though
I expected my query to mean (in the context of the incorrect results above)
select * from users where users.user_name = 'admin' and users.token = ''
select * from users where users.user_name = '' and users.token = ''
and this query is correct on the console, i.e. produces zero results (ran against the database).
The ORM one, however, seems to discard non-existing headers and assume they are fine (this is at least my understanding)
I also tried to chain the Where clauses via
db.Where(&User{UserName: userHeader}).Where(&User{Token: tokenHeader}).Find(&auth)
but the result is the same.
What should be the correct query?
The gorm.io documentation says the following on the use of structs in Where conditionals:
When querying with struct, GORM will only query with non-zero fields,
that means if your field’s value is 0, '', false or other zero
values, it won’t be used to build query conditions ...
The suggested solution to this is:
To include zero values in the query conditions, you can use a map,
which will include all key-values as query conditions ...
So, when the token header or both headers are empty, but you still want to include them in the WHERE clause of the generated query, you need to use a map instead of the struct as the argument to the Where method.
db.Where(map[string]interface{}{"user_name": userHeader, "token": tokenHeader}).Find(&auth)
You can use Debug() to check for the generated SQL (it gets printed into stderr); use it if you are unsure what SQL your code generates

How do use fuzzy matching validation for either a non-present key or an empty array?

In karate version 0.9.6 I used the following match statement in a .feature file and it worked for validating the value to be an empty array or a key that was not present.
def example = {}
match example.errors == '##[0]'
In 1.0 the documentation example suggests that this should check for the key being present and null or an empty array and testing this fails with a validation error that the value is not present.
From https://karatelabs.github.io/karate/#schema-validation
# should be null or an array of strings
* match foo == '##[] #string'
This appears to be an undocumented breaking change from pre-1.0 to 1.0.
My question is: how do I construct a validator to cover this case correctly when the key is allowed to be absent but if it is present it must be an empty array?
I've found an undesirable solution for now but am leaving this open in case someone has a better answer.
I'm validating the entire parent object with a minimal schema:
Replace
match $.errors == '##[0]'
With
* match $ == { data: '#object', extensions: '##object', errors: '##[0]' }
While more brittle and verbose it is technically working.
This indeed looks like an in-intended breaking change. Here is another workaround:
* def example = {}
* def expected = example.errors ? '#[0]' : '#notpresent'
* match example.errors == expected
I see you have opened an issue here: https://github.com/karatelabs/karate/issues/1825
EDIT: this might be an improvement over the workaround you came up with in your answer:
* match example contains { errors: '##[0]' }

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.