Response body: JSON value is equal or greater than

Yes - also a solution. :slight_smile:

Maybe a one more hint - not necessarily in this case. If you had more values to verify, you’d use for-each loop for verification. It is more clear and elegant solution.

def totalValue = parsedJson.total
def availableValue = parsedJson.available
def pendingValue = parsedJson.pending
def paidValue = parsedJson.paid

List vals = Arrays.asList(totalValue, availableValue, pendingValue, paidValue)

for(def val in vals) {
	CustomKeywords.'verify.VerifyValues.valueIsPresent'(val)
	CustomKeywords.'verify.VerifyValues.valueIsEqualOrGreaterThan'(val)
}
1 Like

Oh, yes, you’re totally right! Thanks!

The code looks nice … but you have a small problem.
If one of the keys is not present in the response … the code will crash exactly there, at the def :slight_smile:
So … you have to improve it a bit, either use json schema validation to check the keys presence, or when you declare the variables, use safe coding. Elvis operator may help:

def totalValue = parsedJson.total ?: 'missing'
-----------------------
	@Keyword
	def valueIsPresent(BigDecimal jsonValue) {
		if(jsonValue == 'missing') {
			KeywordUtil.markFailed("Key is not present")
		}
	}

1 Like

Yes, I’ve already faced that, so thank you again :slight_smile:

Also, there is another inconvenient.
If any of the key is not present (or have the wrong value) the execution will stop and the other’s verification skipped.
So you have to use also failure handling if this is a problem for you, see:
https://docs.katalon.com/katalon-studio/docs/failure-handling.html

1 Like

I think I have to use:

	@Keyword
	def valueIsPresent(BigDecimal jsonValue) {
		if(jsonValue == 'missing' || jsonValue == null) {
			KeywordUtil.markFailed("Key is not present")
		}
	}

And I see another problem… Oh, while I was typing a message you’ve already describe it :slight_smile:

this is redundant if you use elvis, see:
http://groovy-lang.org/operators.html#_elvis_operator

the ‘?:’ will do exactly this for you, if null or empty will assign the value from the right to the variable :slight_smile:

1 Like

Oh, it’s like a ternary operator in JS, it seems that for me the holidays have not ended yet :slight_smile:

Yeah, is a ternary on steroids :smiley:

:+1::grinning:

@Ibus,

I don’t know why but if I get such response:

{
  "total":6.98,
  "available":0.0,
  "pending":0.0,
  "paid":6.98
}

At the line:

def availableValue = parsedJson.available ?: 'missing'

I get 'missing' instead of expected value and of course than:

ERROR k.k.c.m.CustomKeywordDelegatingMetaClass - ? No signature of method: verify.VerifyValues.valueIsPresent() is applicable for argument types: (java.lang.String) values: [missing]
Possible solutions: valueIsPresent(java.math.BigDecimal)

and so on…

My bad. ‘missing’ is a string :smiley: and your keyword expect a BigDecimal.
Use another safe value instead … e. g -1

the failure in fact appears here, when trying to compare the BigDecimal with the string:

if(jsonValue == 'missing')

It seems it’s some kind of another problem because of after changing to def availableValue = parsedJson.available ?: -1 I get:

ERROR k.k.c.m.CustomKeywordDelegatingMetaClass - ? com.kms.katalon.core.exception.StepFailedException: Key has incorrect value

It seems to me at the line def availableValue = parsedJson.available ?: -1 availableValue always gets -1 value if the response is "available":0.0.

chh … i think groovy truth is playing with you, since 0 will evaluate to false:
http://docs.groovy-lang.org/latest/html/documentation/core-semantics.html#Groovy-Truth

So it may be solved with the plain ternary:

availableValue = (parsedJson.available!=null) ? parsedJson.available : -1.0

Sometime, abusing on steroids is a bad idea!

LE: on the other side we just find out that , using the Elvis, you can collapse your code to use a single keyword, like keyIsPresentAndGreatherThanZero :smiley: since 0.0 will always be false

1 Like

You’re right :+1: And I still have to use the plain ternary since I need to verify if the value is equal or greater than zero :slight_smile:

Thanks!


Thanks to all at now my keywords are:

...

class VerifyValues {
	@Keyword
	def valueIsPresent(BigDecimal jsonValue) {
		if(jsonValue == -1.0) {
			KeywordUtil.markFailedAndStop("Key is not present")
		}
	}
	@Keyword
	def valueIsEqualOrGreaterThan(BigDecimal jsonValue) {
		BigDecimal cBase = 0.0
		if(jsonValue.compareTo(cBase) == -1) {
			KeywordUtil.markFailedAndStop("Key has incorrect value")
		}
	}
}

And verification code is:

...

'Set variables'

String jsonString = response.getResponseText()

JsonSlurper slurper = new JsonSlurper()
Map parsedJson = slurper.parseText(jsonString)

def totalValue = (parsedJson.total != null) ? parsedJson.total : -1.0
def availableValue = (parsedJson.available != null) ? parsedJson.available : -1.0
def pendingValue = (parsedJson.pending != null) ? parsedJson.pending : -1.0
def paidValue = (parsedJson.paid != null) ? parsedJson.paid : -1.0

List values = Arrays.asList(totalValue, availableValue, pendingValue, paidValue)

'Verify if all keys are present and their values are correct'

for(def val in values) {
	CustomKeywords.'verify.VerifyValues.valueIsPresent'(val)
	CustomKeywords.'verify.VerifyValues.valueIsEqualOrGreaterThan'(val)
}
1 Like

The power of cooperation. :slight_smile: Nice!

1 Like

I played a bit in IDEA (i cannot make KatalonGUI to work properly in Linux … yet).
Maybe you can use this too:

import groovy.json.JsonSlurper

jsonString = """
{
  "total":6.98,
  "available":0.0,
  "pending":0.0
}
"""

//'Set variables'
//
//String jsonString = response.getResponseText()
//
JsonSlurper slurper = new JsonSlurper()
Map parsedJson = slurper.parseText(jsonString)

List keysToCheck = Arrays.asList('total', 'available', 'pending', 'paid')
keysToCheck.each { it ->
    valToCheck = (parsedJson.get(it) != null) ? parsedJson.get(it) : -1.0
    println("${it} : ${valToCheck}")
    //    CustomKeywords.'verify.VerifyValues.valueIsPresent'(valToCheck)
    //    CustomKeywords.'verify.VerifyValues.valueIsEqualOrGreaterThan'(valToCheck)
}

OUTPUT
total : 6.98
available : 0.0
pending : 0.0
paid : -1.0

For the complete Json the output is:

total : 6.98
available : 0.0
pending : 0.0
paid : 6.98
1 Like

More ‘groovyfication’ (We don’t need def or explicit types in a groovy script :wink: . Also, it is the default iterator so we can get rid of it)

slurper = new JsonSlurper()
parsedJson = slurper.parseText(jsonString)

keysToCheck = ['total', 'available', 'pending', 'paid']

keysToCheck.each {
    valToCheck = (parsedJson.get(it) != null) ? parsedJson.get(it) : -1.0
    println("${it} : ${valToCheck}")
    //    CustomKeywords.'verify.VerifyValues.valueIsPresent'(valToCheck)
    //    CustomKeywords.'verify.VerifyValues.valueIsEqualOrGreaterThan'(valToCheck)
}
1 Like

@Ibus,

I have this keyword:

class VerifyValues {
	@Keyword
	def valueIsPresentAndIsEqualOrGreaterThan(BigDecimal jsonValue) {
		if(jsonValue == -1.0) {
			KeywordUtil.markFailedAndStop("Key is not present")
		}
		BigDecimal cBase = 0.0
		if(jsonValue.compareTo(cBase) == -1) {
			KeywordUtil.markFailedAndStop("Key has incorrect value")
		}
	}
}

And this verification code:

JsonSlurper slurper = new JsonSlurper()
parsedJson = slurper.parseText(jsonString)

keysToCheck = ['total', 'available', 'pending', 'paid']

keysToCheck.each { it ->
    valToCheck = (parsedJson.get(it) != null) ? parsedJson.get(it) : -1.0
    println("${it} : ${valToCheck}")
	CustomKeywords.'verify.VerifyValues.valueIsPresentAndIsEqualOrGreaterThan'(valToCheck)
}

If my input is one of those variation all works fine:

String jsonString = '''{
	"total":6.98,
	"available":0.0,
	"pending":-20.0,
	"paid":6.98
}'''

or

String jsonString = '''{
	"total":6.98,
	"available":0.0,
	"pendingssssssssss":0.0,
	"paid":6.98
}'''

But if I use:

String jsonString = '''{
	"total":6.98,
	"available":0.0,
	"pending":-1.0,
	"paid":6.98
}'''

I get Key is not present because it matches -1.0 in valToCheck = (parsedJson.get(it) != null) ? parsedJson.get(it) : -1.0

Well I can use some other number and hope that there will never be matches.

And if I use:

String jsonString = '''{
	"total":6.98,
	"available":0.0,
	"pending":,
	"paid":6.98
}'''

I get:

Verification FAILED Reason: groovy.json.JsonException: Unable to determine the current character, it is not a string, number, array, or object

In this way parsedJson.get(it) != null is not processed correctly. I think I don’t understand something :slight_smile:

I was expecting this :smiley:

With case by case verification, more situations can occur (as you just find out, value missing, or value is a string etc etc)

Therefore … JSON schema validation to the rescue, otherwise you will have to treat all such edge cases and the code will start to be full of exceptions

If not in hurry, tomorrow I will be back at work and i will share again the code of the keyword I use (I am lazy today to re-write it)

the last error you get is due to a malformed Json.